一、队列
1.1先进先出
import queue #导入队列模块
q = queue.Queue(3) #实例化一个队列对象,允许在里面放入3个数据
q.put(123)
q.put('you are my sunshine')
q.put([1,2,3,4])
print(q.get())
print(q.get())
print(q.get())
'''
123
you are my sunshine
[1, 2, 3, 4]
'''
1.2先进后出(堆栈)
q = queue.LifoQueue() #实例化一个队列,这个队列的原则是先进后出
q.put(123)
q.put('you are my sunshine')
q.put([1,2,3,4])
print(q.get())
print(q.get())
print(q.get())
'''
[1, 2, 3, 4]
you are my sunshine
123
'''
1.3 按优先级进出
q= queue.PriorityQueue(3) #实例化一个优先级输出数据的队列的对象
q.put((1,'A')) #括号里面是一个元祖,通常这个元祖的第一个值是int类型
q.put((2,'B'))
q.put((3,'C'))
print(q.get()) #(1, 'A') 先输出优先级高的
q= queue.PriorityQueue(3)
q.put((1,'emmm')) #括号里面是一个元祖
q.put((1,'aaaa'))
q.put((3,'emmm'))
print(q.get()) #(1, 'aaaa') 当前面的数字一样时,后面的字符串是按照Ascall码排
二、定时器
import time
from threading import Thread,Timer
def task():
print('线程开始')
time.sleep(1.5)
print('线程结束')
t = Timer(3,task) #3秒之后开启一个线程,也就是说3秒之后打印出来了子线程中的内容
t.start()
三、线程池与进程池
池的功能是限制进程数或线程数,当并发的任务数远远大于计算机所能承受的范围,即无法开启过多的任务数,我们就应该考虑限制进程数或者线程数,从而保证服务器不崩。
3.1 线程池
from concurrent.futures import ThreadPoolExecutor
from threading import currentThread
import time
def task(i):
time.sleep(1.5)
print(f"{currentThread().name}在执行任务{i+1}")
return i**2
if __name__ == '__main__':
fu_list = []
pool = ThreadPoolExecutor(4) #规定线程池有是个线程
for i in range(20): #模拟20个线程,task要做20次,4个线程负责做这个事情
future = pool.submit(task,i) #for循环一次,提交一次
fu_list.append(future) #先把提交的数据意义放到这个列表里面
pool.shutdown() # 关闭池的入口,不让你往里面再放东西
for fu in fu_list: #依次循环列表里面的值
print(fu.result()) #打印返回值
'''
ThreadPoolExecutor-0_1在执行任务2
ThreadPoolExecutor-0_0在执行任务1
ThreadPoolExecutor-0_3在执行任务4
ThreadPoolExecutor-0_2在执行任务3
ThreadPoolExecutor-0_1在执行任务6
ThreadPoolExecutor-0_0在执行任务5
ThreadPoolExecutor-0_2在执行任务7
ThreadPoolExecutor-0_3在执行任务8
'''
.......
3.2 进程池
from concurrent.futures import ProcessPoolExecutor
from multiprocessing import current_process
import time
def task(i):
time.sleep(1)
print(f"{current_process().name}在执行任务{i+1}")
time.sleep(1)
return i**2
if __name__ == '__main__':
fu_list = []
pool = ProcessPoolExecutor(4) #规定进程池有是个线程
for i in range(20): #模拟20个进程,task要做20次,4个进程负责做这个事情
future = pool.submit(task,i) #for循环一次,提交一次
fu_list.append(future) #先把提交的数据意义放到这个列表里面
pool.shutdown() # 关闭池的入口,不让你往里面再放东西
for fu in fu_list:
print(fu.result())
'''
SpawnProcess-1在执行任务1
SpawnProcess-2在执行任务2
SpawnProcess-3在执行任务3
SpawnProcess-4在执行任务4
SpawnProcess-1在执行任务5
SpawnProcess-2在执行任务6
SpawnProcess-3在执行任务7
SpawnProcess-4在执行任务8
.......
'''
四、提交任务的两种方式
4.1 同步
提交了一个任务,必须等任务执行完 (拿到返回值)才能执行下一行代码
import os
import time
import random
from multiprocessing import Process
def work(n):
print(f'{n}: {os.getpid()} is running' )
time.sleep(random.randint(1,3))
print('%s:%s is done' %(n,os.getpid()))
if __name__ == '__main__':
for i in range(3): #这种就是同步了
p=Process(target=work,args=(i,))
p.start()
4.2 异步
提交了一个任务,不需要等任务执行完 (拿到返回值)才能执行下一行代码,就可以直接执行下一行
from concurrent.futures import ProcessPoolExecutor
from multiprocessing import current_process
import time
def task(i):
time.sleep(1)
print(f"{current_process().name}在执行任务{i+1}")
time.sleep(1)
return i**2
def parse(future):
print(future.result())
if __name__ == '__main__':
fu_list = []
pool = ProcessPoolExecutor(4) #规定进程池有是个线程
for i in range(20): #模拟20个进程,task要做20次,4个进程负责做这个事情
future = pool.submit(task,i) #for循环一次,提交一次
future.add_done_callback(parse)
# 为当前任务绑定了一个函数,在当前任务执行结束的时候会触发这个函数,
# 会把future对象作为参数传给函数
# 这个称之为回调函数,处理完了回来就调用这个函数.