一、线程池
from concurrent.futures import ThreadPoolExecutor import time def func(n): time.sleep(2) print(n) return n * n def call_back(m): print("结果是:%s" % m.result()) # 拿到结果 tpool = ThreadPoolExecutor(max_workers=5) # 默认不要超过cpu个数+1 # tpool.map(func,range(10)) # 使用map拿不到返回值 # for i in range(10): # t = tpool.submit(func, i).add_done_callback(call_back) # 回调函数 t_list = [] for i in range(10): t = tpool.submit(func, i) # 一次五个,异步执行 t_list.append(t) # tpool.shutdown() # 起到 close 和join 作用 阻塞,所有线程池执行完 print("主线程:") for t in t_list: print("***", t.result()) # 拿到返回值"""
二、全局解释器锁:gil
全局锁:同一时刻只能有一个线程访问CPU,在Cpython中 在同一时刻 多个线程只能有一个被执行。
原因:多个线程被CPU调度处理数据中,在解释型语言中系统没法识别,多个线程是否会在同一时刻访问相同数据,会出现不同CPU在同一时 刻,分别调用同一进程下多个线程,访问同一数据,进行增删改查,造成数据混乱,全局锁的出现就是为加强对数据的安全!
疑问:既然有了全局锁为何数据还需要加锁?
在全局变量中,多进程或者多线程去访问同一数据,当其中一个进程或者线程拿到数据,释放了全局锁,突然遇到阻塞,其他进程或者线程这 时候拿到也拿到相同数据,同时去执行,也会造成数据混乱。
什么时候选择多进程和多线程:
高CPU:计算类>>>>>>>高CPU利用率(多进程)
高IO:input 爬取网页 ,qq聊天,处理日志文件,读文件,处理web请求,读写数据库等等>>>>>>(多线程)
三、线程(信号量和事件)
1.多线程信号量:
from threading import Semaphore, Thread import time def func(sem, a, b): time.sleep(1) sem.acquire() print(a + b) sem.release() sem = Semaphore(4) for i in range(10): t = Thread(target=func, args=(sem, i, i + 5)) t.start()
2.事件
应用:连接数据库 ,检测数据库的可连接情况
起两个线程:
第一个线程:连接数据库
等待一个信号 告诉我们之间的网络是通的
第二个线程:检测与数据库之间的网络是否连通
time。sleep(0,2) 2 将事件设置为True
# 事件被创建的时候
# false 状态 wait()阻塞
# true 状态 wait()非阻塞
# clear 设置状态为 False
# set 设置状态为 True"""
mport time, random from threading import Event, Thread def connect(e): count = 0 while count < 3: e.wait(1) # 状态为False 的时候,我只等待1s就结束 if e.is_set() == True: print("连接数据库成功!") break else: count += 1 print("第%d次连接失败" % count) else: raise TimeoutError("数据库连接异常") def check_web(e): time.sleep(random.randint(0, 3)) e.set() e = Event() t1 = Thread(target=connect, args=(e,)) t2 = Thread(target=check_web, args=(e,)) t1.start() t2.start()
四、条件
Condition条件:更复杂锁
提供 acquire release
一个条件被创建之初,默认有一个False状态
False状态 会影响wait 一直处于等待状态
notify(int数据类型)制造几把钥匙,就能过去几个线程"""
from threading import Condition, Thread def func(con, i): con.acquire() con.wait() # 一直在等待钥匙,然后放行,有一把放一个,有10个放十个 print("在第%s个循环里" % i) con.release() con = Condition() for i in range(10): Thread(target=func, args=(con, i,)).start() while True: num = int(input(">>>>>>>:")) con.acquire() con.notify(num) # 造钥匙 con.release()
五、定时器
from threading import Timer import time def func(): print("时间同步") while True: t = Timer(5, func).start() # 非阻塞 time.sleep(5) # 每5秒执行一次
六、线程队列
import queue q = queue.Queue() q.put(1) q.put(2) # q.put_nowait() q.get() # q = queue.LifoQueue() # 栈 先进后出 # q.put(1) # q.put(2) # q.put(3) # print(q.get()) # print(q.get()) # print(q.get()) q = queue.PriorityQueue() # 优先级队列,谁的数小谁先出去 q.put((20, "a")) q.put((10, "b")) q.put((30, "c")) q.put((1, "d")) print(q.get())