学习python多线程之前先思考两个问题:
1、为什么要使用多线程?
2、python多线程运行机制?
GIL-全局解释器锁
官网地址:threading — Thread-based parallelism — Python 3.8.12 documentation
文章目录:
1、线程类 threading
2、线程对象 ()
2.1、创建线程的两种方法
2.2、守护线程
3、线程锁对象
3.1、互斥锁
3.2、递归锁
4、条件对象 ()
5、信号量对象 ()
6、事件对象
7、Timer计时器对象
1、线程类 threading
- current_thread() 返回与Thread调用方的控制线程相对应的当前对象。
- enumerate() 返回Thread当前所有活动对象的列表。
- active_count() 返回Thread当前活动的对象数。返回的计数等于所返回列表的长度enumerate()。
- main_thread() 返回主要Thread对象。在正常情况下,主线程是启动Python解释器的线程。
- get_ident() 返回当前线程的“线程标识符”。这是一个非零整数。它的值没有直接的意义。
2、线程对象 ()
- start() 启动线程的活动。
- join() 等待线程终止。这将阻塞调用线程,直到join()被调用方法的线程终止(正常或通过未处理的异常终止),或者直到发生可选的超时。
- setDaemon() 守护线程
- getName()获取当前活动线程的名称
2.1、创建线程的两种方法
"""
创建线程的方法一:
创建一个()对象,参数如下:
_init__(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None)
group:group参数必须为空,参数group是预留的,用于将来扩展;
target: 参数target是一个可调用对象(也称为活动[activity]),在线程启动后执行
name: 参数name是线程的名字。默认值为“Thread-N“,N是一个数字。
args:以元组的方式,为 target 指定的方法传递参数;
kwargs:以字典的方式,为 target 指定的方法传递参数;
daemon:指定所创建的线程是否为后代线程。
"""
import threading
import time
def run():
"""
threading.current_thread().getName() 获取当前线程的名字,默认Thread-n格式
如果创建线程组的时候参数name有值,则取指定的name值。
:return:
"""
print(threading.current_thread().getName(),())
(1)
print(threading.current_thread().getName(),())
(1)
print(threading.current_thread().getName(),())
(1)
print(threading.current_thread().getName(),())
(1)
if __name__ == '__main__':
"""不带参数的线程 """
t1 = (target=run)
t2 = (target=run)
()
()
#也可以使用for方法来实现多个线程,也可以将多个线程放在一个列表中来遍历
# for i in range(5):
# t=(target=function)
# ()
D:\github\Python\threading_study>python threading_study01.py
Thread-1 Thu Oct 15 11:10:55 2020
Thread-2 Thu Oct 15 11:10:55 2020
Thread-1 Thu Oct 15 11:10:56 2020
Thread-2 Thu Oct 15 11:10:56 2020
Thread-1 Thu Oct 15 11:10:57 2020
Thread-2 Thu Oct 15 11:10:57 2020
Thread-1 Thu Oct 15 11:10:58 2020
Thread-2 Thu Oct 15 11:10:58 2020
D:\github\Python\threading_study>
"""
创建线程的方法二:
自定义线程:继承来定义线程类,然后重写__init__方法和run方法,使用start方法来启动线程。
"""
import threading
import time
class MyThread():
def __init__(self):
"""
重写__init__方法,可以使用super来调用父类的方法
:param name:
"""
# super().__init__()
.__init__(self)
def run(self):
"""
重写run方法,注意方法名只能是 run
这里也可以调用其他方法
:return:
"""
print(threading.current_thread().getName(), ())
(1)
print(threading.current_thread().getName(), ())
(1)
print(threading.current_thread().getName(), ())
(1)
print(threading.current_thread().getName(), ())
if __name__ == '__main__':
t1 = MyThread()
t2 = MyThread()
()
()
D:\github\Python\threading_study>python threading_study02.py
Thread-1 Thu Oct 15 11:12:43 2020
Thread-2 Thu Oct 15 11:12:43 2020
Thread-1 Thu Oct 15 11:12:44 2020
Thread-2 Thu Oct 15 11:12:44 2020
Thread-1 Thu Oct 15 11:12:45 2020
Thread-2 Thu Oct 15 11:12:45 2020
Thread-1 Thu Oct 15 11:12:46 2020
Thread-2 Thu Oct 15 11:12:46 2020
D:\github\Python\threading_study>
2.2、守护线程
"""
守护线程:
主线程不管守护线程的执行情况,只要是其他子线程结束且主线程执行完毕,主线程都会关闭。
常见方法:
1、setDaemon(True)方法可以把子线程设置为主线程的守护线程,此方法必须在start之前
2、join()方法,让主线程等待子线程执行,此方法在start之后
"""
import threading
import time
def run1(name,n):
for _ in range(n): #_下划线表示临时变量, 仅用一次,后面无需再用到
print(name,())
(1)
def run2(name,n):
for _ in range(n):
print(name,())
(1)
if __name__ == '__main__':
"""
设置子线程t1为守护线程,主线程不等t1运行结束,只要其他的子线程t2运行结果,就会关闭主线程。
"""
t1 = (target=run1,args=("线程1",10,)) #注意args参数类型是元组并以“,”结尾
t2 = (target=run2,args=("线程2",5,))
(True) #设置t1为守护线程
()
()
# () ##设置主线程等待子线程t1运行结束
D:\github\Python\threading_study>python threading_study03.py
线程1 Thu Oct 15 11:17:08 2020
线程2 Thu Oct 15 11:17:08 2020
线程1 Thu Oct 15 11:17:09 2020
线程2 Thu Oct 15 11:17:09 2020
线程1 Thu Oct 15 11:17:10 2020
线程2 Thu Oct 15 11:17:10 2020
线程1 Thu Oct 15 11:17:11 2020
线程2 Thu Oct 15 11:17:11 2020
线程1 Thu Oct 15 11:17:12 2020
线程2 Thu Oct 15 11:17:12 2020
线程1 Thu Oct 15 11:17:13 2020
D:\github\Python\threading_study>
3、线程锁对象
- acquire() 锁定,一旦线程获取了锁,随后的尝试将其阻塞,直到释放为止。任何线程都可以释放它。
- release() 解锁
3.1、互斥锁
"""
线程锁-互斥锁
为什么要使用线程锁分析:/JackLiu16/article/details/81267176
互斥锁运行顺序分析:/weixin_40481076/article/details/101594705
"""
import threading,time
#实例化一个互斥锁对象
lock = ()
def run():
() #获取锁
print(threading.current_thread().getName(),())
(5)
() #释放锁
for _ in range(10):
t = (target=run)
()
D:\github\Python\threading_study>python threading_study04.py
Thread-1 Thu Oct 15 11:19:13 2020
Thread-2 Thu Oct 15 11:19:18 2020
Thread-3 Thu Oct 15 11:19:23 2020
Thread-4 Thu Oct 15 11:19:28 2020
Thread-5 Thu Oct 15 11:19:33 2020
Thread-6 Thu Oct 15 11:19:38 2020
Thread-7 Thu Oct 15 11:19:43 2020
Thread-8 Thu Oct 15 11:19:48 2020
Thread-9 Thu Oct 15 11:19:53 2020
Thread-10 Thu Oct 15 11:19:58 2020
D:\github\Python\threading_study>
3.2、递归锁
"""
递归锁:
互斥锁如果嵌套了多个锁之后,会将自己锁死永远都出不来了。
这个时候可以使用递归锁,它相当于一个字典,记录了锁的门与锁的对应值,当开门的时候会根据对应来开锁。
"""
import threading,time
# 生成递归锁实例
lock = ()
# run1第二道锁
def run1():
with lock: #在with语句中使用锁,条件和信号量
print("run1",threading.current_thread().getName(),())
# run2第三道锁
def run2():
with lock:
print("run2",threading.current_thread().getName(),())
# run3相当于第一道锁
def run3():
()
run1()
(5)
print("run3",threading.current_thread().getName(),())
(5)
run2()
()
# 循环开启10个线程
for i in range(10):
t = (target=run3)
()
()
D:\github\Python\threading_study>python threading_study05.py
run1 Thread-1 Thu Oct 15 11:20:53 2020
run3 Thread-1 Thu Oct 15 11:20:58 2020
run2 Thread-1 Thu Oct 15 11:21:03 2020
run1 Thread-2 Thu Oct 15 11:21:03 2020
run3 Thread-2 Thu Oct 15 11:21:08 2020
run2 Thread-2 Thu Oct 15 11:21:13 2020
run1 Thread-3 Thu Oct 15 11:21:13 2020
run3 Thread-3 Thu Oct 15 11:21:18 2020
run2 Thread-3 Thu Oct 15 11:21:23 2020
run1 Thread-4 Thu Oct 15 11:21:23 2020
run3 Thread-4 Thu Oct 15 11:21:28 2020
run2 Thread-4 Thu Oct 15 11:21:33 2020
run1 Thread-5 Thu Oct 15 11:21:33 2020
run3 Thread-5 Thu Oct 15 11:21:38 2020
run2 Thread-5 Thu Oct 15 11:21:43 2020
run1 Thread-6 Thu Oct 15 11:21:43 2020
run3 Thread-6 Thu Oct 15 11:21:48 2020
run2 Thread-6 Thu Oct 15 11:21:53 2020
run1 Thread-7 Thu Oct 15 11:21:53 2020
run3 Thread-7 Thu Oct 15 11:21:58 2020
run2 Thread-7 Thu Oct 15 11:22:03 2020
run1 Thread-8 Thu Oct 15 11:22:03 2020
run3 Thread-8 Thu Oct 15 11:22:08 2020
run2 Thread-8 Thu Oct 15 11:22:13 2020
run1 Thread-9 Thu Oct 15 11:22:13 2020
run3 Thread-9 Thu Oct 15 11:22:18 2020
run2 Thread-9 Thu Oct 15 11:22:23 2020
run1 Thread-10 Thu Oct 15 11:22:23 2020
run3 Thread-10 Thu Oct 15 11:22:28 2020
run2 Thread-10 Thu Oct 15 11:22:33 2020
D:\github\Python\threading_study>
4、条件对象 ()
- 可以把Condiftion理解为一把高级的琐,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。
5、信号量对象 ()
- Semaphore() 内部计数器
- BoundedSemaphore() 继承Semaphore类,设定信号量边界值
"""
信号量(BoundedSemaphore类):
信号量通常用于保护容量有限的资源
信号量管理一个内部计数器,该内部计数器随每个acquire()调用而递减,并随每个 调用而递增release()。
计数器永远不能低于零。当acquire() 发现它为零时,它将阻塞,直到其他线程调用为止 release()。
参考地址:/chengd/articles/
"""
import threading,time
#设置信号量的边界值
semaphore = (value=3)
def run():
() #加锁
print(threading.current_thread().getName(),())
(5)
() #释放
if __name__ == '__main__':
for _ in range(10):
t = (target=run)
()
#返回Thread当前所有活动对象的列表。通过运行结果我们可以看出系统是先一次性创建10个线程,然后根据信号量边界值3,一次性运行3个线程,其他线程等待锁。
print(())
"""
python多线程的缺陷:
1、GIL-全局解释器锁
2、无论系统CPU是几核的,只能使用一个来处理进程
/xiangsikai/p/
"""
D:\github\Python\threading_study>python threading_study06.py
Thread-1 Thu Oct 15 11:23:17 2020
Thread-2 Thu Oct 15 11:23:17 2020
Thread-3 Thu Oct 15 11:23:17 2020
[<_MainThread(MainThread, started 13328)>,
<Thread(Thread-1, started 14328)>, <Thread(Thread-2, started 15192)>,
<Thread(Thread-3, started 14300)>, <Thread(Thread-4, started 15620)>,
<Thread(Thread-5, started 13720)>, <Thread(Thread-6, started 12456)>,
<Thread(Thread-7, started 9652)>, <Thread(Thread-8, started 15724)>,
<Thread(Thread-9, started 14172)>, <Thread(Thread-10, started 4132)>]
Thread-4 Thu Oct 15 11:23:22 2020
Thread-5 Thu Oct 15 11:23:22 2020
Thread-6 Thu Oct 15 11:23:22 2020
Thread-7 Thu Oct 15 11:23:27 2020
Thread-9 Thu Oct 15 11:23:27 2020
Thread-8 Thu Oct 15 11:23:27 2020
Thread-10 Thu Oct 15 11:23:32 2020
D:\github\Python\threading_study>
6、事件对象
- set() 将“Flag”设置为True
- clear() 将“Flag”设置为False
- wait(timeout=None) 如果“Flag”值为 False,那么当程序执行 方法时就会阻塞;如果“Flag”值为True,那么执行 方法时便不再阻塞。
- is_set() 判断“Flag”值是否为True。
"""
事件对象
set() 将“Flag”设置为True
clear() 将“Flag”设置为False
wait() 如果“Flag”值为 False,主线程就会阻塞;如果“Flag”值为True,主线程不再阻塞。
isSet() 判断“Flag”值是否为True。
"""
import threading
import time
#实例化一个事件对象
event = ()
def run():
while not ():
print(threading.current_thread().getName(), ())
(5)
(timeout=10) # 阻塞线程,为什么timeout=10没起到作用
if __name__ == '__main__':
#使用多线程去调用run
for i in range(10):
th = (target=run)
()
#阻塞30s后运行主线程
(30)
()
D:\github\Python\threading_study>python threading_study07.py
Thread-1 Thu Oct 15 11:25:08 2020
Thread-2 Thu Oct 15 11:25:08 2020
Thread-3 Thu Oct 15 11:25:08 2020
Thread-4 Thu Oct 15 11:25:08 2020
Thread-5 Thu Oct 15 11:25:08 2020
Thread-6 Thu Oct 15 11:25:08 2020
Thread-7 Thu Oct 15 11:25:08 2020
Thread-8 Thu Oct 15 11:25:08 2020
Thread-9 Thu Oct 15 11:25:08 2020
Thread-10 Thu Oct 15 11:25:08 2020
Thread-1 Thu Oct 15 11:25:13 2020
Thread-2 Thu Oct 15 11:25:13 2020
Thread-4 Thu Oct 15 11:25:13 2020
Thread-6 Thu Oct 15 11:25:13 2020
Thread-3 Thu Oct 15 11:25:13 2020
Thread-8 Thu Oct 15 11:25:13 2020
Thread-5 Thu Oct 15 11:25:13 2020
Thread-9 Thu Oct 15 11:25:13 2020
Thread-7 Thu Oct 15 11:25:13 2020
Thread-10 Thu Oct 15 11:25:13 2020
Thread-1 Thu Oct 15 11:25:18 2020
Thread-2 Thu Oct 15 11:25:18 2020
Thread-4 Thu Oct 15 11:25:18 2020
Thread-6 Thu Oct 15 11:25:18 2020
Thread-3 Thu Oct 15 11:25:18 2020
Thread-8 Thu Oct 15 11:25:18 2020
Thread-5 Thu Oct 15 11:25:18 2020
Thread-9 Thu Oct 15 11:25:18 2020
Thread-7 Thu Oct 15 11:25:18 2020
Thread-10 Thu Oct 15 11:25:18 2020
Thread-1 Thu Oct 15 11:25:23 2020
Thread-2 Thu Oct 15 11:25:23 2020
Thread-4 Thu Oct 15 11:25:23 2020
Thread-6 Thu Oct 15 11:25:23 2020
Thread-3 Thu Oct 15 11:25:23 2020
Thread-5 Thu Oct 15 11:25:23 2020
Thread-8 Thu Oct 15 11:25:23 2020
Thread-9 Thu Oct 15 11:25:23 2020
Thread-7 Thu Oct 15 11:25:23 2020
Thread-10 Thu Oct 15 11:25:23 2020
Thread-1 Thu Oct 15 11:25:28 2020
Thread-2 Thu Oct 15 11:25:28 2020
Thread-4 Thu Oct 15 11:25:28 2020
Thread-6 Thu Oct 15 11:25:28 2020
Thread-3 Thu Oct 15 11:25:28 2020
Thread-5 Thu Oct 15 11:25:28 2020
Thread-8 Thu Oct 15 11:25:28 2020
Thread-9 Thu Oct 15 11:25:28 2020
Thread-7 Thu Oct 15 11:25:28 2020
Thread-10 Thu Oct 15 11:25:28 2020
Thread-1 Thu Oct 15 11:25:33 2020
Thread-2 Thu Oct 15 11:25:33 2020
Thread-4 Thu Oct 15 11:25:33 2020
Thread-6 Thu Oct 15 11:25:33 2020
Thread-5 Thu Oct 15 11:25:33 2020
Thread-3 Thu Oct 15 11:25:33 2020
Thread-8 Thu Oct 15 11:25:33 2020
Thread-7 Thu Oct 15 11:25:33 2020
Thread-9 Thu Oct 15 11:25:33 2020
Thread-10 Thu Oct 15 11:25:33 2020
Thread-1 Thu Oct 15 11:25:38 2020
D:\github\Python\threading_study>
7、Timer计时器对象
- 参数:(self, interval, function, args=None, kwargs=None)
- start() 启动计时器
- cancel() 停止计时器(在其动作开始之前)
"""
Timer对象
"""
import threading
#实例化一个计时器
timer =
def hello():
print("hello, world")
#10s后执行hello
t = timer(10, hello)
()
D:\github\Python\threading_study>python threading_study08.py
hello, world
D:\github\Python\threading_study>