Python 学习笔记: 多线程
多线程
1、 多线程的TCP server 聊天
from threading import Thread import socket def chat(conn): conn.send(b'hello') msg = conn.recv(1024).decode('utf-8') print(msg) if __name__ == '__main__': sk = socket.socket() sk.bind(('127.0.0.1', 8090)) sk.listen() while True: conn, addr = sk.accept() t = Thread(target=chat, args=(conn,)) t.start() sk.close()
2 、 守护线程, 会等待所有的线程结束才结束
from threading import Thread import time def func1(): print('start thread func...') while True: print('*'*10) time.sleep(1) def func2(): print('thread func2 start...') time.sleep(4) print('thread func2 end...') t1 = Thread(target=func1,) t1.daemon = True t1.start() t2 = Thread(target=func2,) t2.start() print('main thread .')
3、线程的递归锁, 例子: 科学家吃面,利用递归锁解决死锁。
from threading import Thread from threading import RLock import time def eat(name): global noodle_rlock global fork_rlock noodle_rlock.acquire() time.sleep(1) fork_rlock.acquire() print('%s 拿到 noodle lock'%name) print('%s 拿到 fork lock'%name) print('%s 吃面。。'%name) fork_rlock.release() noodle_rlock.release() noodle_rlock = fork_rlock = RLock() Thread(target=eat,args=('alex',)).start() Thread(target=eat,args=('jinboss',)).start() Thread(target=eat,args=('boke',)).start() Thread(target=eat,args=('kilin',)).start()
4、事件, 连接数据库前,测试连接数据库连接是否成功。
import time from threading import Thread,Event import random def conn_db(e): count = 0 while count < 3: e.wait(0.5) if e.is_set(): print('第%s次连接数据库成功'%(count+1)) break else: count += 1 print('第%s次连接数据库失败' %(count)) else: # raise TimeoutError('连接数据库超时') print('连接数据库超时') def check_db(e): time.sleep(random.randint(0,4)) e.set() e = Event() t1 = Thread(target=check_db, args=(e,)) t2 = Thread(target=conn_db, args=(e,)) t1.start() t2.start()
5 条件Condition
from threading import Condition, Thread def func(con,i): con.acquire() con.wait() print('进程%s %s在执行中...'%(i,Thread.ident)) 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()
例如: 输入3时, con.notify(3) , 发布3把钥匙。 会有3个线程开始执行。
6、线程池 使用concurrent.futures 包
import time import random from concurrent.futures import ThreadPoolExecutor def func(n): time.sleep(random.randint(1,3)) print('in thread %s'%n) return n*n tpool = ThreadPoolExecutor(5) t_plist=[] for i in range(20): t = tpool.submit(func,i) t_plist.append(t) print('main threading') tpool.shutdown() for t in t_plist: print('***',t.result())
带call back 函数时,返回值是一个结果的对象。 需要result()方法取得结果
import time from concurrent.futures import ThreadPoolExecutor def func(n): time.sleep(2) print('in thread %s'%n) return n*n def call_back(m): print('结果是 %s'%m.result()) tpool = ThreadPoolExecutor(5) for i in range(20): tpool.submit(func,i).add_done_callback(call_back) print('main threading')