定时器、线程queue、进程池和线程池

1.定时器

指定n秒后,执行任务

 1 from threading import Timer,current_thread
 2 import os
 3 
 4 
 5 def hello():
 6     print("%s hello, world"%os.getpid())
 7     print("%s hello, world"%current_thread().name)
 8 
 9 
10 t = Timer(3, hello)
11 t.start()  # after 1 seconds, "hello, world" will be printed
12 print(os.getpid())
13 print(current_thread())
14 
15 # 12376
16 # <_MainThread(MainThread, started 12008)>
17 # 12376 hello, world
18 # Thread-1 hello, world
定时器

2.线程queue

2.1 先进先出

 1 import queue
 2 
 3 q=queue.Queue()
 4 q.put('first')
 5 q.put('second')
 6 q.put('third')
 7 
 8 print(q.get())
 9 print(q.get())
10 print(q.get())
11 '''
12 结果(先进先出):
13 first
14 second
15 third
16 '''
先进先出

2.2 后进先出

 1 import queue
 2 
 3 q=queue.LifoQueue()
 4 q.put('first')
 5 q.put('second')
 6 q.put('third')
 7 
 8 print(q.get())
 9 print(q.get())
10 print(q.get())
11 '''
12 结果(后进先出):
13 third
14 second
15 first
16 '''
后进先出

2.3 优先级队列(开了会员就要先出来)

存储数据时可以设置优先级队列。数字越小(可以为负数),优先级越高,取出来的是一个元组形式。

里面put什么值就取出来什么值,只是优先级的问题。

 1 import queue
 2 
 3 q=queue.PriorityQueue()
 4 #put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
 5 q.put((20,'a'))
 6 q.put((10,'b'))
 7 q.put((30,'c'))
 8 
 9 print(q.get())
10 print(q.get())
11 print(q.get())
12 '''
13 结果(数字越小优先级越高,优先级高的优先出队):
14 (10, 'b')
15 (20, 'a')
16 (30, 'c')
17 '''
优先级队列

3.进程池和线程池

'''
1、什么时候用池:
池的功能是限制启动的进程数或线程数,
什么时候应该限制???
当并发的任务数远远超过了计算机的承受能力时,即无法一次性开启过多的进程数或线程数时
就应该用池的概念将开启的进程数或线程数限制在计算机可承受的范围内

2、同步vs异步
同步、异步指的是提交任务的两种方式

同步:提交完任务后就在原地等待,直到任务运行完毕后拿到任务的返回值,再继续运行下一行代码
异步:提交完任务(绑定一个回调函数)后根本就不在原地等待,直接运行下一行代码,等到任务有
返回值后会自动触发回调函数

'''
concurrent.futures 高度封装的异步调用接口
ProcessPoolExecutor 进程池 提供异步调用
ThreadPoolExecutor 线程池 提供异步调用

 1 from socket import *
 2 
 3 sever = socket(AF_INET,SOCK_STREAM)
 4 sever.bind(("127.0.0.1",8080))
 5 sever.listen(5)
 6 # 无法实现并发,建立一个连接,进入通信循环,直到通信循环结束
 7 while True:
 8     conn,addr = sever.accept()
 9     while True:
10         try:
11             data = conn.recv(1024)
12             if len(data) == 0:break
13             conn.send(data.upper())
14         except ConnectionResetError:
15             break
16     sever.close()
17 
18 
19 from socket import *
20 
21 sever = socket(AF_INET,SOCK_STREAM)
22 sever.bind(("127.0.0.1",8080))
23 sever.listen(5)
24 def task(conn):
25     while True:
26         try:
27             data = conn.recv(1024)
28             if len(data) == 0: break
29             conn.send(data.upper())
30         except ConnectionResetError:
31             break
32     sever.close()
33 # 还是实现不了并发,只能实现串行
34 while True:
35     conn,addr = sever.accept()
36     task(conn)
37 
38 from socket import *
39 from threading import Thread
40 
41 sever = socket(AF_INET,SOCK_STREAM)
42 sever.bind(("127.0.0.1",8080))
43 sever.listen(5)
44 def task(conn):
45     while True:
46         try:
47             data = conn.recv(1024)
48             if len(data) == 0: break
49             conn.send(data.upper())
50         except ConnectionResetError:
51             break
52     sever.close()
53 
54 # 启动一个子线程干通信的活
55 # 每建立一个连接就开启一个子线程,交给子线程干通信的活,可以实现并发
56 while True:
57     conn,addr = sever.accept()
58 
59     t = Thread(target=task,args=(conn,))
60     t.start()
61 
62 from socket import *
63 from threading import Thread
64 
65 def task(conn):
66     while True:
67         try:
68             data = conn.recv(1024)
69             if len(data) == 0: break
70             conn.send(data.upper())
71         except ConnectionResetError:
72             break
73     sever.close()
74 
75 # 将while循环放到函数下面,可以往里面传入ip,port和半连接池的最大限制数
76 # 这样做是已经实现并发了,但是如果有很多的客户请求,需要不停的建立线程数,电脑肯定是有上限的。
77 # python中的线程是操作系统的原生线程,需要操作系统来调度,同时开启太多线程,操作系统调度不过来。
78 # 限制线程数不是为了提高效率,是高并发情况下不得已而为之
79 def sever_func(ip,port,backlog = 5):
80     while True:
81         sever = socket(AF_INET,SOCK_STREAM)
82         sever.bind((ip, port))
83         sever.listen(backlog)
84         print("start-------")
85         conn,addr = sever.accept()
86 
87         t = Thread(target=task,args=(conn,))
88         t.start()
89 
90 if __name__ == '__main__':
91     sever_func("127.0.0.1",8080)
串行到并发改进

同步

同步:提交完任务后就在原地等待,直到任务运行完毕后拿到任务的返回值,再继续运行下一行代码
同步调用并不是真正意义上的串行,只是他的取值方式让程序变成了串行的工作方式。
 1 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 2 import time
 3 import os
 4 
 5 
 6 def task(n):
 7     print("%s is running"%os.getpid())
 8     time.sleep(5)
 9     return n**2
10 
11 # 默认是cpu的个数
12 # 如果直接在提交任务后拿到返回值就变成同步了
13 if __name__ == '__main__':
14     pool = ProcessPoolExecutor(4)
15     l = []
16     for i in range(1,10):
17         future = pool.submit(task,i)
18         l.append(future)
19         # print(future)
20         # print(future.result())
21     pool.shutdown(wait=True)
22     for m in l:
23         print(m.result())
同步调用

异步 

异步:提交完任务(绑定一个回调函数)后根本就不在原地等待,直接运行下一行代码,等到任务有
返回值后会自动触发回调函数
回调函数:parse会在futrue有返回值时立刻触发,并且将future当作参数传给parse

 1 from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
 2 from threading import current_thread
 3 import os
 4 import time
 5 import random
 6 
 7 def task(n):
 8     print('%s run...' %current_thread().name)
 9     time.sleep(5)
10     return n**2
11 
12 def parse(future):
13     time.sleep(1)
14     res=future.result()
15     print('%s 处理了 %s' %(current_thread().name,res))
16 
17 if __name__ == '__main__':
18     pool=ThreadPoolExecutor(4)
19     start=time.time()
20     for i in range(1,5):
21         future=pool.submit(task,i)
22         future.add_done_callback(parse) # parse会在futrue有返回值时立刻触发,并且将future当作参数传给parse
23     pool.shutdown(wait=True)
24     stop=time.time()
25     print('',current_thread().name,(stop - start))
异步调用+回掉函数
原文地址:https://www.cnblogs.com/Roc-Atlantis/p/9323135.html