案例:
开启 5 个线程,每个线程中都获取一个随机数,输出5个随机数的总和
回顾进程和线程
一个进程中默认会产生一个主线程
, 除此之外,还可以人为开启并启动额外线程, 有以下特点:
1、不干预的情况下,各个线程的执行过程都互不影响,不会形成阻塞
2、各个线程共享本进程的全局变量,因此操作共享资源时,需要考虑线程安全问题
使用 threading.Thread
使用 threading.Thread 创建
使用 .start() 方法启动线程
from threading import Thread
t = Thread(target=线程要执行的函数, args=执行函数的参数列表)
t.start()
way1 使用线程安全对象 list
import time
import random
from threading import Thread
def way1():
def get_random_int(contains):
time.sleep(2)
contains.append(int(random.random() * 10))
contains = []
for i in range(5):
t = Thread(target=get_random_int, args=(contains,))
t.start()
while len(contains) != 5:
time.sleep(2)
print(f"results:{contains}\n{sum(contains)}")
way2 使用 join 方法合并线程
join 方法涉及两个角色:调用join的线程对象、执行join的线程对象
如下例中:
t 为 调用join的线程对象
主线程 为 执行join的线程对象
主线程将会被阻塞,直到 t 线程结束
t = Thread(...) # 创建了一个额外工作线程
t.start()
t.join() # t 为 调用join的线程对象
# 主线程 为 执行join的线程对象
使用 join
import time
import random
from threading import Thread
def way2_use_join():
def get_random_int(contains):
time.sleep(2)
contains.append(int(random.random() * 10))
contains, ts = [], []
for i in range(5):
t = Thread(target=get_random_int, args=(contains,))
t.start()
ts.append(t)
for t in ts:
t.join()
print(f"results:{contains}\n{sum(contains)}")
way3 使用互斥锁 Lock 确保数据安全
def way3_use_join_lock():
def get_random_int(result):
time.sleep(2)
lock.acquire()
num = int(random.random() * 10)
print(f"num:{num}")
result[0] += num
lock.release()
result, ts = [0], []
lock = Lock()
for i in range(5):
t = Thread(target=get_random_int, args=(result, ))
t.start()
ts.append(t)
for t in ts:
t.join()
print(f"result:{result[0]}")