一、Python实现多线程的几种方式
_thread:模块提供了基本的线程和互斥锁支持;更底层的的线程管理实现模块 threading:threading模块则通过封装_thread,提供了更加全面的线程使用方法。 _thread案例:# *coding:utf-8 * #用_thread启动多个线程完成任务 import _thread import threading #板砖的动作 import time global brick_list brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"] def action(): while True: if len(brick_list) ==0: break brick_list.pop() #搬砖 print(threading.currentThread(),"还剩%s" % (brick_list)) time.sleep(0.1) def main(): #自己一个人搬 # action() #请一个人 # _thread.start_new_thread(action,()) #请100个人,多个子进程运行 for i in range(100): _thread.start_new_thread(action, ()) time.sleep(10) if __name__ == '__main__': main()关键代码解释:
_thread.start_new_thread(action, ()) 启动一个新的线程,执行action函数,threading案例:
# *coding:utf-8 * import _thread import threading #板砖的动作 import time global brick_list brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"] def action(): while True: if len(brick_list) ==0: break brick_list.pop() #搬砖 print(threading.currentThread(),"还剩%s" % (brick_list)) time.sleep(0.1) def main(): #启动两个线程搬砖 # t1=threading.Thread(target=action,args=()) # t2=threading.Thread(target=action,args=()) # t1.start() # t2.start() #启动100个线程搬砖 for i in range(100): temp=threading.Thread(target=action,name="thread"+ str(i),args=()) temp.start() time.sleep(10) if __name__ == '__main__': main()关键代码解释:
threading.Thread(target=action,name="thread1", args=()) 创建一个线程,这个线程默认没有启动,需要继续调用start()来启动 例如:threading.Thread(target=action,name="thread1", args=()).start() 其中,target用要执行的任务函数,name是线程名,args是传递给执行的任务函数值
二、Threading多线程编程
2.1线程阻塞
Thread().join()作用:阻塞主线程的运行,让主线程等待所有子线程运行结束之后,再继续运行
# *coding:utf-8 * import _thread import threading #板砖的动作 import time global brick_list brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"] def action(): while True: if len(brick_list) ==0: break brick_list.pop() #搬砖 print(threading.currentThread(),"还剩%s" % (brick_list)) time.sleep(0.1) def main(): t1=threading.Thread(target=action,name="1号码农",args=(),daemon=True) #daemon=True为守护进程,当主线程结束也会随之结束 t1.start() t1.join() #阻塞主线程 if __name__ == '__main__': main()
2.2 守护线程和非守护线程
获取Thread对象后,通过Thread对象中__init__方法中的daemon参数来设置守护线程和非守护线程,默认是非守护线程。 守护线程:其他线程都运行结束后,守护线程立即结束 非守护线程:无论其他线程有没有运行结束,本线程都必须正常运行结束后才会结束。import threading import time from time import sleep def action(max): for i in range(max): print(threading.currentThread().name+"{}次循环\n".format(i)) time.sleep(1) def main(): t = threading.Thread(target=action, args=(10000,), name='后台线程') t.daemon = True #设置为守护线程 # 启动后台线程 t.start() for i in range(10): print(threading.current_thread().name+"主线程循环了{}次".format(i)) print("主线程运行结束了") if __name__ == '__main__': main()2.3 线程锁(Lock)和信号量 线程锁(Lock): 为了防止线程与线程之间资源共享导致的线程安全问题,我们可以对访 问的资源加上锁,这个锁就是线程锁。 信号量:信号量是指控制有多少个线程可以访问的相同资源 2.3.1线程锁案例: Lock对象方法: acquire() 获取锁 release() 释放锁
import threading from time import sleep result = 0 #获取锁对象 lock=threading.Lock() def add(): global result lock.acquire() #加锁 for i in range(1000000): result = result + 1 lock.release() #解锁 print("%s 的resul的结果为:%s" % (threading.current_thread().name,result)) def main(): thread_list = [] for i in range(3): thread_list.append(threading.Thread(target=add, name="t" + str(i))) # 初始化3个线程, #并把线程对象添加到thread_list中 for i in range(3): thread_list[i].start() # 启动thread_list中的3个线程 if __name__ == '__main__': main()2.3.2信号量案例:
import threading,time semaphore=threading.Semaphore(500) #只允许500个人进入地铁站,执行运输任务 def action(counts): print("{}乘客来到地铁站".format(counts)) semaphore.acquire() # 获得信号量:信号量减一 print("{}乘客已进站".format(counts)) time.sleep(10) semaphore.release() #释放信号量:信号量加一 print("{}乘客已出站".format(counts)) def main(): for i in range(10000): t = threading.Thread(target=action, args=(i,)) t.start() if __name__ == '__main__': main()
三、队列和线程池
1、队列用法:
from queue import Queue #创建队列 q = Queue(maxsize=10)队列常见操作方法:
Queue.qsize() 返回队列的大小 Queue.empty() 如果队列为空,返回True,反之False Queue.full() 如果队列满了,返回True,反之False Queue.full 与 maxsize 大小对应 Queue.get([block[, timeout]])获取队列,timeout等待时间 Queue.get_nowait() 相当Queue.get(False) Queue.put(item) 写入队列,timeout等待时间 Queue.put_nowait(item) 相当Queue.put(item, False) Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列 发送一个信号 Queue.join() 实际上意味着等到队列为空,再执行别的操作
案例:
import random import threading from queue import Queue import time q=Queue(10) #启动一个队列大小是10,能放10个菜 food_menu = ["佛跳墙", "红烧狮子头", "东坡肉", "蚂蚁 上树", "鱼香肉丝", "麻婆豆腐", "鱼子酱", "意大利面", "土豆丝炒肉", "银耳羹", "窝窝头", "糖醋排骨"] def make_lunch(): """服务端""" print("开始做菜") while True: if q.full(): #队列满了 print("菜做好了") q.join() #等待食客吃饭 food_number=random.randint(0,len(food_menu)-1) q.put(food_menu[food_number]) # 写入队列 print("做了:", food_menu[food_number]) time.sleep(0.5) def ear_lunch(): time.sleep(10) # 等才做好了再开始吃 while True: if q.empty(): #队列消息为空 print("吃完了再来一顿") time.sleep(10) else: food_name=q.get() #获取队列消息 print("吃了",food_name) q.task_done() def main(): #定义两个消息队列,并开启服务 cooker=threading.Thread(target=make_lunch,args=(),name="cooker") eater=threading.Thread(target=ear_lunch,args=(),name="cooker") cooker.start() eater.start() if __name__ == '__main__': main()
2、线程池:
顾名思义就是存放线程的池子,线程池可以控制线程的启动数量,从而达到节省系统资源的目的 作用:可以控制要启动的线程数量。 线程池与信号量Semaphore的区别: 线程池控制的是线程数量,而信号量控制的是并发数量。 超过信号量规定数量的线程,已经被启动了,只是状态是挂起。而线程池中,超过了线 程池规定数量的线程,还没有启动,只能等待启动。使用方式:
threadpool库是第三方的库,所以必须要进行安装#线程池案例 import threading import threadpool import time brick_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"] def action(brick): print(threading.currentThread().name+"搬出了: ",brick) time.sleep(0.2) def main(): tp=threadpool.ThreadPool(5) #设置5个线程 requests=threadpool.makeRequests(action,brick_list) for req in requests: tp.putRequest(req) tp.wait() if __name__ == '__main__': main()
四、tomorrow库:多线程并发测试库
pip install tomorrow 具体案例:#使用tomorrow来完成“听歌、聊天、吃饭”三件事儿 import time from random import random from tomorrow import threads import threading @threads(10) # 最多开启10个线程完成任务 def task( task_name): print( threading.current_thread().name +"正在:", task_name) if __name__ == '__main__': task_name_list = ["砖头1", "砖头2", "砖头3", "砖头4", "砖头5", "砖头6", "砖头7","砖头8", "砖头9", "砖头10", "砖头11", "砖头12", "砖头13", "砖头14", "砖头15", "砖头16", "砖头17", "砖头18", "砖头19", "砖头20", "砖头21", "砖头22", "砖头23", "砖头24", "砖头25", "砖头26", "砖头27", "砖头28", "砖头29", "砖头30","砖头31", "砖头32", "砖头33", "砖头34", "砖头35", "砖头36", "砖头37", "砖头38", "砖头39", "砖头40", "砖头41", "砖头42", "砖头43", "砖头44", "砖头45", "砖头46", "砖头47", "砖头48", "砖头49", "砖头50","砖头51", "砖头52", "砖头53", "砖头54", "砖头55", "砖头56", "砖头57", "砖头58", "砖头59", "砖头60","砖头61", "砖头62", "砖头63", "砖头64", "砖头65", "砖头66", "砖头67", "砖头68", "砖头69", "砖头70", "砖头71", "砖头72", "砖头73", "砖头74", "砖头75", "砖头76", "砖头77", "砖头78", "砖头79", "砖头80", "砖头81", "砖头82", "砖头83", "砖头84", "砖头85", "砖头86", "砖头87", "砖头88", "砖头89", "砖头90","砖头91", "砖头92", "砖头93", "砖头94", "砖头95", "砖头96", "砖头97", "砖头98", "砖头99", "砖头100"] for i in range(0,len(task_name_list)-1): task(task_name_list[i]) time.sleep(0.2)
标签:__,进阶,16,threading,线程,import,砖头,多线程,name From: https://www.cnblogs.com/xfbk/p/17747596.html