目录
本片转自https://home.cnblogs.com/u/fxyadela
socket多线程
客户端
import socket
from threading import Thread
def client_demo():
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('192.168.11.199', 8010))
while True:
msg = f'{currentThread().name}'
if len(msg) == 0: break
client.send(msg.encode('utf-8'))
feedback = client.recv(1024)
print(feedback.decode('utf-8'))
client.close()
if __name__ == '__main__':
for i in range(5):
t = Thread(target=client_demo)
t.start()
服务端
import socket
from threading import Thread
def talk(conn):
while True:
try:
msg = conn.recv(1024)
if len(msg) == 0: break
conn.send(msg.upper())
except connectionResetError
print('客户端关闭了一个链接')
break
conn.close()
def serve_demo():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('192.168.11.199', 8010))
server.listen(5)
while True:
conn, addr = server.accept()
t = Thread(target=talk, args(conn,))
t.start()
if __name__ == '__main__':
server_demo()
线程queue
用法一:先进先出(Queue)
import queue
q = queue.Queue()
q.put('123')
q.put('qweqwe')
print(q.get())
print(q.get())
q.task_done()
q.task_done()
123
qweqwe
用法二:先进后出(LifoQueue)
堆栈
import queue
q = queue.LifoQueue()
q.put('粉红色的背心儿')
q.put('粉红色的裤子')
q.put('欧文的各种设备')
print(q.get())
print(q.get())
print(q.get())
欧文的各种设备
粉红色的裤子
粉红色的背心儿
用法三:优先级(PriorityQueue)
通常这个元组的第一个值是int类型
import queue
# 可以根据优先级取数据
q = queue.PriorityQueue()
q.put((50, '吴磊'))
q.put((80, '陈飞宇'))
q.put((1, '欧阳娜娜'))
print(q.get())
print(q.get())
print(q.get())
(1, '欧阳娜娜')
(50, '吴磊')
(80, '陈飞宇')
线程定时器
介绍
启动某个线程的倒计时
from threading import Thread
import time
def task():
print('线程执行!')
time.sleep(1)
print('线程结束!')
t = Timer(3, task) #3秒后执行task
t.start()
==》时间过去3秒
线程执行了
==》时间过去2秒
线程结束了
进程池和线程池
介绍
例子(进程池)
from concurrent.future import ProcessPoolExecutor, ThreadPoolExecutor
from threading import currentThread
from multiprocessing import current_process
import time
def task(i):
print(f'{current_process().name}在执行任务{i}')
time.sleep(1)
return i**2
if __name__ == '__main__':
pool = ProcessPoolExecutor(3) # 池子里只有3个线程
fu_list = []
for i in range(9):
future = pool.submit(task, i) # task任务要做9次, 3个进程负责做这个事
fu_list.append(future)
pool.shutdown() # 关闭了池的入口,会等待所有的任务执行完,结束阻塞
for fu in fu_list:
print(fu.result())
进程 SpawnProcess-1 在执行任务 0
进程 SpawnProcess-2 在执行任务 1
进程 SpawnProcess-3 在执行任务 2
进程 SpawnProcess-1 在执行任务 3
进程 SpawnProcess-2 在执行任务 4
进程 SpawnProcess-3 在执行任务 5
进程 SpawnProcess-1 在执行任务 6
进程 SpawnProcess-2 在执行任务 7
进程 SpawnProcess-3 在执行任务 8
0
1
4
9
16
25
36
49
64
例子(线程池)
from concurrent.future import ProcessPoolExecutor, ThreadPoolExecutor
from threading import currentThread
from multiprocessing import current_process
import time
def task(i):
print(f'{currentThread().name}在执行任务{i}')
time.sleep(1)
return i**2
if __name__ == '__main__':
pool = ThreadPoolExecutor(3) # 池子里只有3个线程
fu_list = []
for i in range(9):
future = pool.submit(task, i) # task任务要做9次, 3个线程负责做这个事
fu_list.append(future)
pool.shutdown() # 关闭了池的入口,会等待所有的任务执行完,结束阻塞
for fu in fu_list:
print(fu.result())
ThreadPoolExecutor-0_0 在执行任务 0
ThreadPoolExecutor-0_1 在执行任务 1
ThreadPoolExecutor-0_2 在执行任务 2
ThreadPoolExecutor-0_2 在执行任务 3
ThreadPoolExecutor-0_0 在执行任务 4
ThreadPoolExecutor-0_1 在执行任务 5
ThreadPoolExecutor-0_0 在执行任务 6
ThreadPoolExecutor-0_1 在执行任务 7
ThreadPoolExecutor-0_2 在执行任务 8
0
1
4
9
16
25
36
49
64
同步和异步
介绍
协程
介绍
什么是协程?
为什么要有协程?
什么样的协程有意义?
协程的优点是什么?
携程的缺点是什么?
例子
情况一:单纯地切换反而会降低运行效率
import time
def consumer(res):
'''任务1:接收数据,处理数据'''
pass
def producer():
'''任务2:生产数据'''
res = []
for i in range(10000000):
res.append(i)
return res
start = time.time()
#串行执行
res = producer()
consumer(res) #写成consumer(producer())会降低执行效率
stop = time.time()
print(stoop - start)
#基于yield并发执行
import time
def consumer():
'''任务1:接收数据,处理数据'''
while True:
x = yield
def producer():
'''任务2:生产数据'''
g = consumer()
next(g)
for i in range(10000000)
g.send(i)
start = time.time()
#基于yield保存状态,实现两个任务直接来回切换,即并发的效果
#PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的
producer()
stop = time.time()
print(stop - start)
情况二:yield不能实现io切换
import time
def consumer():
'''任务1:接收数据, 处理数据'''
while True:
x = yield
def producer():
'''任务2:生产数据'''
g = consumer()
next(g)
for i in range(10000000):
g.send(i)
time.sleep(2)
start = time.time()
producer() #并发执行,但是任务producer遇到io就会阻塞住,并不会切到该线程内的其他任务去执行
stop = time.time()
print(stop - start)
gevent模块
介绍
例子
情况一:gevent
遇到io阻塞时会自动切换任务
import gevent
def eat(name):
print(f'{name} eat 1')
time.sleep(2)
print(f'{name} eat 2')
def play(name):
print(f'{name} play 1')
time.sleep(3)
print(f'{name} play 2')
g1 = gevent.spawn(eat, 'ada')
g2 = gevent.spawn(play, name = 'ada')
g1.join() #等待g1结束
g2.join() #等待g2结束
print('主')
情况二:from gevent import money;money.patch_all()
from gevent import monkey;monkey.patch_all()
import gevent
import time
def eat():
print('eat 1')
time.sleep(2)
print('eat 2')
def play():
print('play 1')
# 疯狂的计算没有io
time.sleep(3)
print('play 2')
start = time.time()
g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join() #等待g1结束
g2.join() #等待g2结束
end = time.time()
print(end-start)