![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
线程基础知识 import os import time from threading import Thread # 多线程并发 # def func(a,b): # global g # g = 0 # print(g,os.getpid()) # # g = 100 # t_lst = [] # for i in range(10): # t = Thread(target=func,args=(i,5)) # t.start() # t_lst.append(t) # for t in t_lst : t.join() # print(g) # class MyTread(Thread): # def __init__(self,arg): # super().__init__() # self.arg = arg # def run(self): # time.sleep(1) # print(self.arg) # # t = MyTread(10) # t.start() # 进程 是 最小的 内存分配单位 # 线程 是 操作系统调度的最小单位 # 线程直接被CPU执行,进程内至少含有一个线程,也可以开启多个线程 # 开启一个线程所需要的时间要远远小于开启一个进程 # 多个线程内部有自己的数据栈,数据不共享 # 全局变量在多个线程之间是共享的 # GIL锁(即全局解释器锁) # 在Cpython解释器下的python程序 在同一时刻 多个线程中只能有一个线程被CPU执行 # 高CPU : 计算类 --- 高CPU利用率 # 高IO : 爬取网页 200个网页 # qq聊天 send recv # 处理日志文件 读文件 # 处理web请求 # 读数据库 写数据库 import time from threading import Thread from multiprocessing import Process def func(n): n + 1 if __name__ == '__main__': start = time.time() t_lst = [] for i in range(100): t = Thread(target=func,args=(i,)) t.start() t_lst.append(t) for t in t_lst:t.join() t1 = time.time() - start start = time.time() t_lst = [] for i in range(100): t = Process(target=func, args=(i,)) t.start() t_lst.append(t) for t in t_lst: t.join() t2 = time.time() - start print(t1,t2)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time import threading def wahaha(n): time.sleep(0.5) print(n,threading.current_thread(),threading.get_ident()) for i in range(10): threading.Thread(target=wahaha,args=(i,)).start() print(threading.active_count()) # 10 print(threading.current_thread()) print(threading.enumerate())
多线程聊天程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket from threading import Thread def chat(conn): conn.send(b'hello') msg = conn.recv(1024).decode('utf-8') print(msg) conn.close() sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() while True: conn,addr = sk.accept() Thread(target=chat,args = (conn,)).start() sk.close()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import socket sk = socket.socket() sk.connect(('127.0.0.1',8080)) msg = sk.recv(1024) print(msg) inp = input('>>> ').encode('utf-8') sk.send(inp) sk.close()
守护线程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time from threading import Thread def func1(): while True: print('*'*10) time.sleep(1) def func2(): print('in func2') time.sleep(5) t = Thread(target=func1,) t.daemon = True t.start() t2 = Thread(target=func2,) t2.start() t2.join() print('主线程') # 守护进程随着主进程代码的执行结束而结束 # 守护线程会在主线程结束之后等待其他子线程的结束才结束 # 主进程在执行完自己的代码之后不会立即结束 而是等待子进程结束之后 回收子进程的资源 # import time # from multiprocessing import Process # def func(): # time.sleep(5) # # if __name__ == '__main__': # Process(target=func).start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time from threading import Lock,Thread # Lock 互斥锁 # def func(lock): # global n # lock.acquire() # temp = n # time.sleep(0.2) # n = temp - 1 # lock.release() # # n = 10 # t_lst = [] # lock = Lock() # for i in range(10): # t = Thread(target=func,args=(lock,)) # t.start() # t_lst.append(t) # for t in t_lst: t.join() # print(n) # 科学家吃面 # noodle_lock = Lock() # fork_lock = Lock() # def eat1(name): # noodle_lock.acquire() # print('%s拿到面条啦'%name) # fork_lock.acquire() # print('%s拿到叉子了'%name) # print('%s吃面'%name) # fork_lock.release() # noodle_lock.release() # # def eat2(name): # fork_lock.acquire() # print('%s拿到叉子了'%name) # time.sleep(1) # noodle_lock.acquire() # print('%s拿到面条啦'%name) # print('%s吃面'%name) # noodle_lock.release() # fork_lock.release() # # Thread(target=eat1,args=('alex',)).start() # Thread(target=eat2,args=('Egon',)).start() # Thread(target=eat1,args=('bossjin',)).start() # Thread(target=eat2,args=('nezha',)).start() from threading import RLock # 递归锁 fork_lock = noodle_lock = RLock() # 一个钥匙串上的两把钥匙 def eat1(name): noodle_lock.acquire() # 一把钥匙 print('%s拿到面条啦'%name) fork_lock.acquire() print('%s拿到叉子了'%name) print('%s吃面'%name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print('%s拿到叉子了'%name) time.sleep(1) noodle_lock.acquire() print('%s拿到面条啦'%name) print('%s吃面'%name) noodle_lock.release() fork_lock.release() Thread(target=eat1,args=('alex',)).start() Thread(target=eat2,args=('Egon',)).start() Thread(target=eat1,args=('bossjin',)).start() Thread(target=eat2,args=('nezha',)).start()
线程的信号量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time from threading import Semaphore,Thread def func(sem,a,b): sem.acquire() time.sleep(1) print(a+b) sem.release() sem = Semaphore(4) for i in range(10): t = Thread(target=func,args=(sem,i,i+5)) t.start()
线程的事件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 事件被创建的时候 # False状态 # wait() 阻塞 # True状态 # wait() 非阻塞 # clear 设置状态为False # set 设置状态为True # 数据库 - 文件夹 # 文件夹里有好多excel表格 # 1.能够更方便的对数据进行增删改查 # 2.安全访问的机制 # 起两个线程 # 第一个线程 : 连接数据库 # 等待一个信号 告诉我我们之间的网络是通的 # 连接数据库 # 第二个线程 : 检测与数据库之间的网络是否连通 # time.sleep(0,2) 2 # 将事件的状态设置为True import time import random from threading import Thread,Event def connect_db(e): count = 0 while count < 3: e.wait(0.5) # 状态为False的时候,我只等待1s就结束 if e.is_set() == True: print('连接数据库') break else: count += 1 print('第%s次连接失败'%count) else: raise TimeoutError('数据库连接超时') def check_web(e): time.sleep(random.randint(0,3)) e.set() e = Event() t1 = Thread(target=connect_db,args=(e,)) t2 = Thread(target=check_web,args=(e,)) t1.start() t2.start()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 条件 from threading import Condition # 条件 # 锁 # acquire release # 一个条件被创建之初 默认有一个False状态 # False状态 会影响wait一直处于等待状态 # notify(int数据类型) 造钥匙 from threading import Thread,Condition def func(con,i): con.acquire() con.wait() # 等钥匙 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()
.
定时器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time from threading import Timer def func(): print('时间同步') #1-3 while True: t = Timer(5,func).start() # 非阻塞的 time.sleep(5)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# queue import queue q = queue.Queue() # 队列 先进先出 # q.put() # q.get() # q.put_nowait() # q.get_nowait() # q = queue.LifoQueue() # 栈 先进后出 # q.put(1) # q.put(2) # q.put(3) # print(q.get()) # print(q.get()) q = queue.PriorityQueue() # 优先级队列 q.put((20,'a')) q.put((10,'b')) q.put((30,'c')) q.put((-5,'d')) q.put((1,'?')) print(q.get())
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import time from concurrent.futures import ThreadPoolExecutor 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个数*5 for i in range(20): tpool.submit(func,i).add_done_callback(call_back) # tpool.map(func,range(20)) # 拿不到返回值 # t_lst = [] # for i in range(20): # t = tpool.submit(func,i) # t_lst.append(t) # tpool.shutdown() # close+join # # print('主线程') # for t in t_lst:print('***',t.result()) # ftp # 并发编程
小结
线程
# 线程是进程中的执行单位
# 线程是cpu执行的最小单位
# 线城之间资源共享
# 线程的开启和关闭以及切换的时间开销远远小于进程
# 线程本身可以在同一时间使用多个cpu
# python 与 线程
# Cpython解释器在解释代码过程中容易产生数据不安全的问题
# GIL 全局解释器锁 锁的是线程
# threading