threading(多线程)模块(待修改)
要点概论:
1. threading模块介绍及常用方法
2. Thread对象
3. 线程同步技术
1 . threading 模块
threading 模块是 python 支持多线程编程的重要模块,该模块是在底层模块 _thread 的基础上开发的更高层次的线程编程接口,提供了大量的方法和类来支持多线程编程,极大的方便了用户。
threading 模块的常用方法:
方法 | 功能说明 |
threading.active_count() | 返回当前处于alive状态的Thread对象数量 |
threading.current_thread() | 返回当前Thread对象 |
threading.get_ident() |
返回当前线程的线程标识符。线程标识符是一个非负整数,并无特殊函数,只是用来标识线程, 该整数可能会被循环利用。python3.3及以后版本支持该方法 |
threading.enumerate() | 返回当前处于alive状态的所有Thread对象列表 |
threading.main_thread() | 返回主线程对象,即启动python解释器的线程对象。python3.4及以后版本支持该方法 |
threading.stack_size[(size)] |
返回创建线程时使用的栈的大小,如果指定size参数,则用来指定后续创建的线程使用的栈大小, size必须是0(表示使用系统默认值)或大于32K的正整数。 |
该模块方法的一些简单用法:
import threading >>>threading.stack_size() #查看当前线程栈的大小 >>>threading.stack_size(64 * 1024) #设置当前线程栈的大小 >>>threading.active_count() #当前活动线程数量 >>>threading.current_thread() #当前线程对象 >>>threading.enumerate() #当前活动线程对象列表
2. Thread 对象
threading 模块提供了 Thread, Lock , Rlock , Ccondition , Event , Timer 和 Semaphore 等大量类来支持多线程编程,
Thread 是其中最重要也是最基本的一个类,可以通过该类创建线程并控制线程的运行。
Thread 类支持使用两种方法来创建线程:一种方法是为构造函数传递一个可调用对象;另一种方法是继承 Thread 类并在派生类中重写 __init__() 和 run() 方法。
创建线程对象以后,可以调用其 start() 方法来启动,该方法自动调用该类对象的 run() 方法,此时该线程处于 alive 状态,直至线程的 run() 方法运行结束。
Thread对象成员:
成员 | 说明 |
start() | 自动调用 run 方法,启动线程,执行线程代码 |
run() |
线程代码,用来实现线程的功能与业务逻辑, 可以在子类中重写该方法来自定义线程的行为 |
__init__(self, group=None, target=None, name=None, |
构造函数 |
name | 用来读取或设置线程的名字 |
ident | 线程标识,非 0 数字或 None (线程未被启动) |
is_alive() , is_Alive() | 测试线程是否处于 alive 状态 |
daemon | 布尔值,表示线程是否为守护线程 |
join(timeout = None) | 等待线程结束或超时返回 |
2.1 Thread 对象中的方法
1) join([timeour]) :阻塞当前线程,等待被调线程结束或超时后再继续执行当前线程的后续代码,参数 timeout 用来指定最长等待时间,单位为秒。
创建多线程:(待验证(把for循环换成普通打印就能对上,WTF?))
import threading import time def func1(x,y): for i in range(x,y): print(i,end='') time.sleep(10) t1 = threading.Thread(target=func1,args=(15,20)) t1.start() t1.join(5) t2 = threading.Thread(target=func1,args=(5,10)) t2.start()
【首先输出 15~19 这 5 个整数,然后程序暂停,几秒钟以后又继续输出 5~9 这 5 个整数。如果将 t1.join(5)这一行注释掉再运行,两个线程的输出将会重叠在一起,
这是因为两个线程并发运行,而不是第一个结束以后再运行第二个。】
2)is_Alive():测试线程是否处于运行状态
查看线程状态:
import threading import time def func1(x,y): for i in range(x,y): print(i,end='') # time.sleep(10) t1 = threading.Thread(target=func1,args=(15,20)) t1.start() t1.join(5) t2 = threading.Thread(target=func1,args=(5,10)) t2.start() t2.join() print('t1:',t1.isAlive()) print('t2:',t2.isAlive())
【最后两个输出都是 Fasle ,即两个线程都执行完了。如果将 ti.join(5) 这一行注释掉会发现最后两行的输出结果没有变化,这是因为 t2,join() 这一行代码会阻塞当前程序直至线程 t2 运行结束,
对于本例中的线程 t1 基本也运行结束了。如果将线程 t1 的参数范围增大则会发现,倒数第二行的输出结果很可能会变为 True。】
2.2 Thread 对象中的 daemon属性
在脚本运行过程中有一个主线程,若在主线程中创建了子线程,当主线程结束时根据子线程 daemon 属性值的不同可能会发生下面的两种情况之一:
①当某子线程的 daemon 属性为 Fasle 时,主线程结束时会检测该子线程是否结束,如果该子线程尚未完成,则主线程会等待它完成后再退出。
②当某子线程的 daemon 属性为 True时,主线程运行结束时不对该子线程进行检查而直接退出,同时所有 daemon 值为 True 的子线程将随主线程一起结束,而不论是否运行完成。
daemon 属性的值默认为 False ,如果需要修改,则必须在调用 start() 方法启动线程之前修改。
PS:以上论述不适用于 IDLE 环境中的交互模式或脚本运行模式,因为在该环境中的主线程只有在退出 python IDLE 时才终止。
1) 线程的 daemon 属性
2) 调用线程对象的普通方法