基础(十五)
概述
- 非并发
程序由单个步骤序列构成,包含独立子任务的程序执行性能低 - 并发
异步高效,分解子任务,简化流程与逻辑 - 进程
一个程序的执行实例,有自己地址空间、内存、数据栈、辅助数据 - 线程
进程内可被并行激活的控制流,共享相同上下文
便于信息共享通信,但访问顺序差异导致结果不一致。 - 全局解释器锁GIL(Global Interpreter Lock)
代码由虚拟机(解释主循环控制),主循环同时只能有一个控制线程执行
多线程
_thread模块
特点
没有控制进程结束机制
只有一个同步原语(锁)
功能少于threading模块
.start_new_thread
.start_new_thread(function,args,**kwargs=None)开始进程
import time
'''单线程例子'''
def worker(n):
print(f'函数执行开始于:{time.ctime()}')
time.sleep(n)
print(f'函数执行结束于:{time.ctime()}')
def main():
print(f'主函数执行开始于:{time.ctime()}')
worker(4)
worker(2)
print(f'主函数执行结束于:{time.ctime()}')
if __name__ == '__main__':
main()
#多线程
import time
import _thread
def worker(n):
print(f'函数执行开始于:{time.ctime()}')
time.sleep(n)
print(f'函数执行结束于:{time.ctime()}')
def main():
print(f'主函数执行开始于:{time.ctime()}')
#执行函数,执行函数参数,参数以元组形式
_thread.start_new_thread(worker,(4,))
_thread.start_new_thread(worker,(2,))
time.sleep(5)
print(f'主函数执行结束于:{time.ctime()}')
if __name__ == '__main__':
main()
threading模块
.Thread 线程类
- 构造
.Thread(target=目标函数,args=(参数,))
自定义Thread派生类,重写run方法逻辑 - .start() 启动线程
- .join() 要求主线程等待执行
#threading多线程
import time
import threading
def worker(n):
print(f'函数执行开始于:{time.ctime()}')
time.sleep(n)
print(f'函数执行结束于:{time.ctime()}')
def main():
print(f'[主函数执行开始于:{time.ctime()}')
#统一发号指令
#线程的实例先不执行放在数组中
threads = []
#创建group-none,target当前线程执行哪个函数
t1 = threading.Thread(target=worker,args=(4,))
threads.append(t1)
t2 = threading.Thread(target=worker,args=(2,))
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
print(f'[主函数执行结束于:{time.ctime()}\n')
if __name__ == '__main__':
main()
.current_thread() 获取当前线程
#threading多线程thread有编号
import time
import threading
def worker(n):
print('{} 函数执行开始于:{}'.format(threading.current_thread().name,time.ctime()))
time.sleep(n)
print(f'{threading.current_thread().name}函数执行结束于:{time.ctime()}')
def main():
print(f'[主函数执行开始于:{time.ctime()}')
#统一发号指令
#线程的实例先不执行放在数组中
threads = []
#创建group-none,target当前线程执行哪个函数
t1 = threading.Thread(target=worker,args=(4,))
threads.append(t1)
t2 = threading.Thread(target=worker,args=(2,))
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
print(f'[主函数执行结束于:{time.ctime()}\n')
if __name__ == '__main__':
main()
#thread类派生类
import time
import threading
def worker(n):
print('{} 函数执行开始于:{}'.format(threading.current_thread().name,time.ctime()))
time.sleep(n)
print(f'{threading.current_thread().name}函数执行结束于:{time.ctime()}')
class MyThread(threading.Thread):
def __init__(self,func,args):
threading.Thread.__init__(self)
self.func = func
self.args = args
def run(self):
#执行自己的函数,传递元组需要解包
self.func(*self.args)
def main():
print(f'[主函数执行开始于:{time.ctime()}')
#统一发号指令
#线程的实例先不执行放在数组中
threads = []
t1 = MyThread(worker,(4,))
threads.append(t1)
t2 = MyThread(worker,(2,))
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
print(f'[主函数执行结束于:{time.ctime()}\n')
if __name__ == '__main__':
main()
threading.Lock 同步原语:锁
.acquire() 获得
.release() 释放
支持上下文操作 with lock:
import threading
import time
'''同步原语——锁——引入'''
eggs = []
def put_egg(n,lst):
for i in range(1,n+1):
lst.append(i)
def main():
threads = []
#创建三个线程
for i in range(3):
#每个线程放5个鸡蛋
t = threading.Thread(target = put_egg,args=(5,eggs))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
print(eggs)
if __name__== '__main__':
main()
输出
D:\python\python.exe F:/teacher/pythonbasetry/day12/mt——4.py
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Process finished with exit code 0
存在弊端:顺序错乱
import threading
import time
import random
'''同步原语——锁——random'''
eggs = []
def put_egg(n,lst):
for i in range(1,n+1):
time.sleep(random.randint(0,2))
lst.append(i)
def main():
threads = []
#创建三个线程
for i in range(3):
#每个线程放5个鸡蛋
t = threading.Thread(target = put_egg,args=(5,eggs))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
print(eggs)
if __name__== '__main__':
main()
D:\python\python.exe F:/teacher/pythonbasetry/day12/mt——4.py
[1, 2, 3, 1, 1, 4, 2, 3, 4, 5, 2, 3, 4, 5, 5]
Process finished with exit code 0
队列
queue 模块
Queue FIFO
.Queue(maxsize=0) 构造实例
.put(item,block=True,timeout=None)放入数据项
.get(block=True,timeout=None) 获取数据项
.task_done() 声明当前队列任务处理完毕
.join() 队列所有项处理完毕前阻塞
LifoQueue LIFO——栈
PriorityQueue 优先队列
import threading
import queue
import time
import random
def producer(data_queue):
for i in range(5):
time.sleep(0.5)
item = random.randint(1,100)
data_queue.put(item)
print(f'{threading.current_thread().name} 在队列中放入数据项:{item}')
def consumer(data_queue):
while True:
try:
item = data_queue.get(timeout=3)
print(f'{threading.current_thread().name} 从队列中移除了{item}')
except queue.Empty:
break
else:
data_queue.task_done()
def main():
q = queue.Queue()
threads = []
p= threading.Thread(target=producer,args=(q,))
p.start()
for i in range(2):
c = threading.Thread(target = consumer,args=(q,))
threads.append(c)
for t in threads:
t.start()
for t in threads:
t.join()
q.join()
if __name__ == '__main__':
main()
mutiprocessing 模块
充分运用多核、多cpu计算能力,适用于计算密集型任务
'''多进程'''
import multiprocessing
import time
def func(n):
print(f'{multiprocessing.current_process().name} 执行开始于 :{time.ctime()}')
time.sleep(n)
print(f'{multiprocessing.current_process().name} 执行结束于 :{time.ctime()}')
def main():
print(f'主函数运行于:{time.ctime()}')
process =[]
p1 = multiprocessing.Process(target=func,args=(4,))
process.append(p1)
p2 = multiprocessing.Process(target=func,args=(2,))
process.append(p2)
for p in process:
p.start()
for p in process:
p.join()
print(f'主函数结束于:{time.ctime()}')
if __name__=='__main__':
main()
concurrent.futures 模块
ThreadPoolExecutor
ProcessPoolExecutor
import time
import concurrent.futures
numbers = list(range(1,11))
def count(n):
for i in range(10000000):
i +=1
return i * n
def worker(x):
result = count(x)
print(f'数字:{x} 的计算结果是:{result}')
# 顺序执行
def sequential_execution():
start_time = time.clock()
for i in numbers:
worker(i)
print(f'顺序执行花费时间:{time.clock()}')
# 线程池
def threading_execution():
start_time = time.clock()
#线程池中最多线程5个
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
for i in numbers:
executor.submit(worker,i)
print(f'线程池执行花费时间:{time.clock()-start_time} 秒')
#进程池执行
def process_execution():
start_time = time.clock()
with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
for i in numbers:
executor.submit(worker,i)
print(f'进程池执行花费时间:{time.clock()-start_time} 秒')
if __name__ == '__main__':
#sequential_execution()
#threading_execution()
process_execution()
process_execution
threading_execution
sequetial_execution