threading
模块是在低级别_thread
模块上构建的的高级别线程接口.继承_thread
功能,易用性更强.
_thread
模块提供处理多进程(也称轻量级继承或任务)的基本单元,多进程控制特点是共享全局数据空间.简单锁(也称互斥或二进制信号量)可实现进程同步.
python线程属于内核级别,即由操作系统调度(如单线程一旦遇到IO就会被迫交出CPU执行权限,切换到其他线程运行).
from threading import *
active_count()
或
import threading
threading.active_count()
序号 | 方法 | 描述 |
---|---|---|
1 | active_count() | 返回Thread对象当前活动的进程数,返回数量与方法enumerate()返回的列表长度一致 |
2 | current_thread() | 返回当前Thread对象相对应控制的线程 |
3 | main_thread() | 返回主线程对象,一般主线程是从Python开始解释(运行)的线程 |
4 | TIMEOUT_MAX | 阻塞最长等待时间 |
5 | enumerate | 返回当前线程对象所有活动的线程列表,列表包括后台进程,current_thread()建立的虚拟线程对象和主线程,不包括结束的线程未启动的线程 |
import threading
counts = threading.active_count()
enu = threading.enumerate()
print("Default thread counts: {}".format(counts))
print("Default thread : {}".format(enu))
print("xindaqi")
Default thread counts: 5
Default thread : [<_MainThread(MainThread, started 139949210203968)>, , , , ]
xindaqi
线程类表示单独控制运行的线程活动.有两种建立线程的方式:
一旦建立线程对象,需使用start()
方法启动线程,这将在独立控制的线程中调用run()
.
线程启动后,该线程被标记为’alive’,当run()
方法终止即结束线程,或抛出错误也会结束线程.线程可设置标志位作为"守护进程",该标志位表示该线程在Pyhton程序运行的整个声明周期,在守护进程退出时结束.
Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
序号 | 方法 | 描述 |
---|---|---|
1 | group | None,未来扩充线程分组时使用 |
2 | target | 被run()方法调用的方法,默认None,无可执行函数 |
3 | name | 线程名称,默认为Thread-N,N为小十进制数 |
4 | args | tuple类型的参数,默认为() |
5 | kwargs | dict类型的参数,默认为{} |
6 | daemon | 线程是否守护进程的标志位,默认为None,后台属性继承当前线程 |
7 | 重写run | 在初始化类时,引用基类结构 Thread.__init __ () |
序号 | 方法 | 描述 |
---|---|---|
1 | start() | 启动线程活动 |
2 | run() | 表示线程活动的方法,可在子类中重写该方法 |
3 | join() | 等待线程结束 |
4 | name | 仅用于标识的字符串 |
5 | daemon | 布尔值,表示线程是否为后台线程,在start()前使用,默认False,当没有活动的前台进程(非后台)进程时,Python程序退出,即通过Thread对象建立的前台进程执行全部结束,程序才退出,若主程序不结束,前台进程会一直运行,需要手动结束;设置为后台进程(daemon=True)时,主程序结束后,这些后台进程会自动结束,无需手动停止. |
import threading
import time
def action(arg):
time.sleep(1)
print("Current thread: {}".format(threading.currentThread().getName()))
print("Threading No.:{}".format(arg))
for i in range(3):
t = threading.Thread(target=action, name="xdq thread {}".format(i), args=(i, ))
t.start()
enu = threading.enumerate()
count = threading.active_count()
print("Threading counts: {}".format(count))
print("Main thread end!")
Threading counts: 6
Threading counts: 7
Threading counts: 8
Main thread end!
Current thread: xdq thread 0
Threading No.:0
Current thread: xdq thread 1
Threading No.:1
Current thread: xdq thread 2
Threading No.:2
import threading
import time
def action(arg):
time.sleep(1)
print("Current thread: {}".format(threading.currentThread().getName()))
print("Threading No.:{}".format(arg))
for i in range(3):
t = threading.Thread(target=action, name="xdq thread {}".format(i), args=(i, ), daemon=False)
t.start()
enu = threading.enumerate()
count = threading.active_count()
print("Threading counts: {}".format(count))
print("Main thread end!")
Threading counts: 6
Threading counts: 7
Threading counts: 8
Main thread end!
Current thread: xdq thread 0
Threading No.:0
Current thread: xdq thread 1
Threading No.:1
Current thread: xdq thread 2
Threading No.:2
import threading
import time
def action(arg):
time.sleep(1)
# 获取当前线程
print("Current thread: {}".format(threading.currentThread().getName()))
print("Threading No.:{}".format(arg))
for i in range(3):
# 新建线程
t = threading.Thread(target=action, name="xdq thread {}".format(i), args=(i, ))
# 获取线程状态
daemon_t = t.isDaemon()
print("Daemon value: {}".format(daemon_t))
# 开启线程
t.start()
# 获取活动线程列表
enu = threading.enumerate()
# 获取活动线程数量
count = threading.active_count()
print("Threading counts: {}".format(count))
print("Enumerate thread: {}".format(enu))
# 主线程
print("Main thread end!")
Threading counts: 6
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , ]
Threading counts: 7
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , , ]
Threading counts: 8
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , , , ]
Main thread end!
Threading No.:0
Threading No.:1
Threading No.:2
此时线程并没有自动结束:
import threading
import time
def action(arg):
time.sleep(1)
# 获取当前线程
print("Current thread: {}".format(threading.currentThread().getName()))
print("Threading No.:{}".format(arg))
for i in range(3):
# 新建线程
t = threading.Thread(target=action, name="xdq thread {}".format(i), args=(i, ), daemon=True)
# 获取线程状态
daemon_t = t.isDaemon()
print("Daemon value: {}".format(daemon_t))
# 开启线程
t.start()
# 获取活动线程列表
enu = threading.enumerate()
# 获取活动线程数量
count = threading.active_count()
print("Threading counts: {}".format(count))
print("Enumerate thread: {}".format(enu))
# 主线程
print("Main thread end!")
Daemon value: True
Threading counts: 6
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , ]
Daemon value: True
Threading counts: 7
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , , ]
Daemon value: True
Threading counts: 8
Enumerate thread: [<_MainThread(MainThread, started 139949210203968)>, , , , , , , ]
Main thread end!
Current thread: xdq thread 0
Threading No.:0
Current thread: xdq thread 1
Threading No.:1
Current thread: xdq thread 2
Threading No.:2
此时线程自动结束:
threading.join()等待线程结束后,在执行下一个线程,保护线程通畅有序执行.
import threading
from threading import Thread, Lock
def add(a, b):
result = a + b
print("result: {} \n".format(result))
desc_th = threading.enumerate()
print("Thread describe: {}".format(desc_th))
count_th = threading.active_count()
print("Counts of thread: {}".format(count_th))
def py_thread():
for i in range(3):
th_1 = Thread(target=add, args=(2, 2), name="a"+str(i), daemon=False)
th_1.start()
if __name__ == "__main__":
py_thread()
print("starting")
result: 4
result: 4
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , , ]
Counts of thread: 7
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , , , ]result: 4
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , , , ]
Counts of thread: 8
Counts of thread: 7
starting
import threading
from threading import Thread, Lock
def add(a, b):
result = a + b
print("result: {} \n".format(result))
desc_th = threading.enumerate()
print("Thread describe: {}".format(desc_th))
count_th = threading.active_count()
print("Counts of thread: {}".format(count_th))
def py_thread():
for i in range(3):
th_1 = Thread(target=add, args=(2, 2), name="a"+str(i), daemon=False)
th_1.start()
th_1.join()
if __name__ == "__main__":
py_thread()
print("starting")
result: 4
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , ]
Counts of thread: 6
result: 4
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , ]
Counts of thread: 6
result: 4
Thread describe: [<_MainThread(MainThread, started 140423660799808)>, , , , , ]
Counts of thread: 6
starting
join
时,如Demo1
所示,有三个线程,第一个线程运行时,还未运行结束,第二个线程开启了,出现先后输出计算结果的情况,即出现了线程混乱;join
方法,即等待线程开启后,等待线程中的所有任务执行后,再去开启下一个线程,保证了当前线程的完整生命周期,这也解决了线程混乱的问题,如Demo2
所示,有三个线程,第一个线程的任务完全结束后,才会开启第二个线程,因此,输出结果是有序的.Python线程间是随机调度的,无优先级,即一个线程a执行多次后,接着执行b线程,当存在多个线程时,容易造成线程混乱,造成资源浪费.
Lock
&RLock
应运而生,基元锁是同步基元,当锁定时不被特定线程占用.Python中,Lock是可用的最低级别的同步基元,可直接被_thread
扩展模块使用.
Lock
基元有锁定和非锁定两种状态,并且他在非锁定状态下创建,拥有acquire()
和release()
两种方法,在非锁定状态时,acquire()
改变线程为锁定状态并立即返回.在锁定状态时,acquire()
阻塞,直到release()
调用另一个线程将其改变为非锁定状态,然后acquire()
重置该线程为锁定状态,并立即返回.release()
方法只在锁定状态是调用,他将线程状态修改为非锁定状态,并立即返回.
当多个线程在acquire()
中处于阻塞状态等待改变为非锁定状态是,release()
只处理一个线程,将其重置为非锁定并返回.
import threading
l = threading.Lock()
l.acquire()
序号 | 方法 | 描述 |
---|---|---|
1 | acquire(blocking=True, timeout=-1) | 获取锁,阻塞或非阻塞,当阻塞参数值为True(默认)时,为阻塞状态,锁为非锁定状态时变为非阻塞状态.,设定为锁定,立即返回;blocking为False时,不阻塞,当blocking设定为True时,线程锁定,返回False,锁定时返回True |
2 | release() | 释放锁,任意线程均可调用,不局限于有lock的线程 |
import threading
import time
g1 = 0
lock = threading.RLock()
def func():
lock.acquire()
global g1
g1 += 1
time.sleep(1)
print("Global value: {}".format(g1))
lock.release()
for i in range(10):
t = threading.Thread(target=func)
t.start()
Global value: 1
Global value: 2
Global value: 3
Global value: 4
Global value: 5
Global value: 6
Global value: 7
Global value: 8
Global value: 9
Global value: 10
import threading
import time
g1 = 0
lock = threading.RLock()
def func():
global g1
g1 += 1
time.sleep(1)
print("Global value: {}".format(g1))
for i in range(10):
t = threading.Thread(target=func)
t.start()
Global value: 10
Global value: 10Global value: 10
Global value: 10
Global value: 10
Global value: 10
Global value: 10
Global value: 10
Global value: 10Global value: 10
[参考文献]
[1]https://docs.python.org/3/library/threading.html
[2]https://www.cnblogs.com/tkqasn/p/5700281.html
[3]https://blog.csdn.net/qq_25343557/article/details/78965044
[4]https://github.com/python/cpython/blob/3.7/Lib/threading.py
[5]https://www.cnblogs.com/xfiver/p/5189732.html
[6]https://www.cnblogs.com/xiao-apple36/p/8683198.html