饮冰三年-人工智能-Python-20 Python线程、进程、线程
进程:最小的数据单元
线程:最小的执行单元
一:
1:线程1
import threading #线程 import time def Music(): print("Listen Music Begin %s" %time.ctime()) time.sleep(3) print("Listen Music End %s" %time.ctime()) def Game(): print("Play Game Begin %s" %time.ctime()) time.sleep(5) print("Play Game End %s" %time.ctime()) if __name__ == '__main__': t1 = threading.Thread(target=Music) t1.start() t2 = threading.Thread(target=Game) t2.start() print("ending......")
import threading #线程 import time def Music(): print("Listen Music Begin %s" %time.ctime()) time.sleep(3) print("Listen Music End %s" %time.ctime()) def Game(): print("Play Game Begin %s" %time.ctime()) time.sleep(5) print("Play Game End %s" %time.ctime()) if __name__ == '__main__': t1 = threading.Thread(target=Music) t1.start() t2 = threading.Thread(target=Game) t2.start() t1.join() t2.join() print("ending......")
import threading #线程 import time def Music(musicName): print("Listen Music【%s】 Begin %s" %(musicName,time.ctime())) time.sleep(3) print("Listen Music【%s】 End %s" %(musicName,time.ctime())) def Game(playName): print("Play Game【%s】 Begin %s" %(playName,time.ctime())) time.sleep(5) print("Play Game【%s】 End %s" %(playName,time.ctime())) if __name__ == '__main__': t1 = threading.Thread(target=Music,args=("My Heart Will Go On",)) t2 = threading.Thread(target=Game,args=("植物大战僵尸",)) threads=[] threads.append(t1) threads.append(t2) for t in threads: t.start(); print("ending......")
import threading #线程 import time def Music(musicName): print("Listen Music【%s】 Begin %s" %(musicName,time.ctime())) time.sleep(3) print("Listen Music【%s】 End %s" %(musicName,time.ctime())) def Game(playName): print("Play Game【%s】 Begin %s" %(playName,time.ctime())) time.sleep(5) print("Play Game【%s】 End %s" %(playName,time.ctime())) t1 = threading.Thread(target=Music,args=("My Heart Will Go On",)) t2 = threading.Thread(target=Game,args=("植物大战僵尸",)) threads=[] threads.append(t1) threads.append(t2) if __name__ == '__main__': t2.setDaemon(True) for t in threads: t.start(); print("ending......")
# 多线程为什么要使用锁? # 多线程共用一个数据集,不使用可能会造成数据不准确 #1:引入多线程模块 import threading import time # 2:定义一个变量(数据集) num=100 # 3:定义一个方法,操作全局变量 def sub(): global num temp = num time.sleep(0.001) num=temp-1 # 4:创建多个线程 ts=[] for i in range(0,100): t=threading.Thread(target=sub) t.start() ts.append(t) for t in ts: t.join() print(num)
# 多线程为什么要使用锁? # 多线程共用一个数据集,不使用可能会造成数据不准确 #1:引入多线程模块 import threading import time # 2:定义一个变量(数据集) num=100 # 3:定义一个方法,操作全局变量 # 5:创建锁 lock=threading.Lock() def sub(): global num # 5.1 加锁 lock.acquire() temp = num time.sleep(0.001) num=temp-1 # 5.2 释放锁 lock.release() # 4:创建多个线程 ts=[] for i in range(0,100): t=threading.Thread(target=sub) t.start() ts.append(t) for t in ts: t.join() print(num)
#当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁 #线程的另一种实现方式(通过自定义类) #1:引入threading、time import threading import time # 定义两个锁 lockA=threading.Lock() lockB=threading.Lock() #3:定义一个线程(线程中存在两个方法,存在递归调用) class MyThread(threading.Thread): #定义两个方法 def actionA(self): # 获取A锁 lockA.acquire() print(self.name,"gotA",time.ctime()) time.sleep(1) #然后再获取B锁 lockB.acquire() print(self.name,"gotB",time.ctime()) time.sleep(2) # 先释放B锁, lockB.release() # 后释放A锁 lockA.release() def actionB(self): # 获取B锁 lockB.acquire() print(self.name, "gotB", time.ctime()) time.sleep(1) # 然后再获取A锁 lockA.acquire() print(self.name, "gotA", time.ctime()) time.sleep(2) # 先释放A锁, lockA.release() # 后释放B锁 lockB.release() #实现run方法 def run(self): self.actionA() self.actionB() # 4:创建多个线程 for i in range(0,5): t=MyThread() t.start()
#当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁 #线程的另一种实现方式(通过自定义类) #1:引入threading、time import threading import time # 定义两个锁 lockA=threading.Lock() lockB=threading.Lock() lockR=threading.RLock() #把两个锁替换成一个RLock,内部通过计数器实现 #3:定义一个线程(线程中存在两个方法,存在递归调用) class MyThread(threading.Thread): #定义两个方法 def actionA(self): # 获取A锁 # lockA.acquire() lockR.acquire() print(self.name,"gotA",time.ctime()) time.sleep(1) #然后再获取B锁 # lockB.acquire() lockR.acquire() print(self.name,"gotB",time.ctime()) time.sleep(2) # 先释放B锁, # lockB.release() lockR.release() # 后释放A锁 # lockA.release() lockR.release() def actionB(self): # 获取B锁 # lockB.acquire() lockR.acquire() print(self.name, "gotB", time.ctime()) time.sleep(1) # 然后再获取A锁 # lockA.acquire() lockR.acquire() print(self.name, "gotA", time.ctime()) time.sleep(2) # 先释放A锁, # lockA.release() lockR.release() # 后释放B锁 lockR.release() # lockB.release() #实现run方法 def run(self): self.actionA() self.actionB() # 4:创建多个线程 for i in range(0,5): t=MyThread() t.start()
# 1:引入包 import threading import time # 2:创建同步锁 event = threading.Event() #3:创建线程对象 class Boss(threading.Thread): def run(self): print("大家加班") event.set() time.sleep(5) print("下班了") event.set() class Worker(threading.Thread): def run(self): event.wait() print("不加班,不加班") time.sleep(1) event.clear() event.wait() print("Oh Yeah") # 4:创建线程对象,并放入到线程集合中 ts=[] t=Boss() ts.append(t) for i in range(0,5): ts.append(Worker()) for t in ts: t.start()
# 信号量类似于停车场,一次只能处理n个线程 # 1:导包 import threading,time # 2:设置信号量 semaphore = threading.Semaphore(5) # 3:创建线程对象 class MyThread(threading.Thread): def run(self): if semaphore.acquire(): print(self.name) time.sleep(3) semaphore.release() # 4:创建线程对象 for i in range(0,20): t=MyThread() t.start()
# 队列:多线程,线程安全 # 1:引包 import queue,time # 2:创建对象 q=queue.Queue(3) #3表示队列的总容量为3、默认为先进先出类型 # 3:常用的方法 q.put("#3333") #添加数据 q.put({"ab":"cd"}) print(q.get()) #获取数据 print(q.qsize()) #获取队列的长度 print(q.empty()) #判断是否为空 print(q.full()) #判断是否已满 print(q.task_done()) #每对队列进行一次操作以后就会返回True print(q.join()) #task_done 对应的就是join
# 通过队列,设置一个生产者消费者的开发模型 # 1:引包 import threading,queue,time,random # 2:定义队列 que=queue.Queue() # 3:定义两个生产者、消费者的类 def Producer(name): countBaoZi=1; while countBaoZi <= 10: # print("包子数量小于10,开始生产包子") time.sleep(random.randrange(1,3)) que.put(countBaoZi) print("生产者:%s,生产了【包子%s】" % (name, countBaoZi)) countBaoZi = countBaoZi + 1 def Consumer(name): countBaoZi=1 while countBaoZi<=10: time.sleep(random.randrange(1,4)) if que.empty(): print("老板没包子了") else: print("现在还有%s个包子" % que.qsize()) curBaoZi = que.get() print("消费者:%s,吃了包子【%s】" % (name, curBaoZi)) # 4:创建多个线程 producerA = threading.Thread(target=Producer,args=("A大厨",)) consumerA = threading.Thread(target=Consumer,args=("A君",)) consumerB = threading.Thread(target=Consumer,args=("B君",)) producerA.start() consumerA.start() consumerB.start()
# 通过队列,设置一个生产者消费者的开发模型 # 升级版,包子吃了以后,还需要再去检查一下,有没有包子if que.empty() 这样浪费时间, # 应该是:吃完就告诉老板直接生产,生产好了再通知客户去吃 # 1:引包 import threading,queue,time,random # 2:定义队列 que=queue.Queue() # 3:定义两个生产者、消费者的类 def Producer(name): countBaoZi=1; while countBaoZi <= 10: time.sleep(random.randrange(1,3)) que.put(countBaoZi) print("生产者:%s,生产了【包子%s】" % (name, countBaoZi)) countBaoZi = countBaoZi + 1 que.join() def Consumer(name): countBaoZi=1 while countBaoZi<=10: time.sleep(random.randrange(1,4)) print("现在还有%s个包子" % que.qsize()) curBaoZi = que.get() time.sleep(1) print("消费者:%s,吃了包子【%s】" % (name, curBaoZi)) que.task_done() # 4:创建多个线程 producerA = threading.Thread(target=Producer,args=("A大厨",)) consumerA = threading.Thread(target=Consumer,args=("A君",)) consumerB = threading.Thread(target=Consumer,args=("B君",)) producerA.start() consumerA.start() consumerB.start()
二 进程
# 1:导包 import time from multiprocessing import Process # 2:创建进程对象集合 pros=[] # 3:定义方法 def music(musicName): print("开始播放:%s.%s" %(musicName,time.ctime())) time.sleep(2) print("播放结束:%s.%s" %(musicName,time.ctime())) def play(gameName): print("开始打:%s.%s" %(gameName,time.ctime())) time.sleep(5) print("游戏结束:%s.%s" %(gameName,time.ctime())) if __name__ == '__main__': # 4:创建进行对象 mu=Process(target=music,args=("My Heart Will Go On",)) mu.start() mg=Process(target=play,args=("植物大战僵尸",)) mg.start()
# 1:导包 import time from multiprocessing import Process # 2:创建进程对象集合 pros=[] # 3:定义方法 def music(musicName): print("开始播放:%s.%s" %(musicName,time.ctime())) time.sleep(2) print("播放结束:%s.%s" %(musicName,time.ctime())) def play(gameName): print("开始打:%s.%s" %(gameName,time.ctime())) time.sleep(5) print("游戏结束:%s.%s" %(gameName,time.ctime())) if __name__ == '__main__': # 4:创建进行对象 mu=Process(target=music,args=("My Heart Will Go On",)) # 4.2:进程常用的属性和方法 #mu.join() #进程阻塞 mu.start() #开启进程 time.sleep(1) mu.terminate() #结束进程 print(" 进程名称 %s, 进程编码 %s,"%(mu.name,mu.pid))
进程之间的三种通讯方法
进程队列
# 1:导包 from multiprocessing import Process,Queue import time #2:定义一个方法,用于向队列中赋值 def putAction(q,n): q.put(n*(n+1)) print("当前队列的id:",id(q)) if __name__ == '__main__': # 3:创建一个队列 que=Queue() print("main方法中队列的id:", id(que)) # 4:通过循环创建多个进程 for i in range(0,3): p=Process(target=putAction,args=(que,i,)) p.start() print(que.get()) print(que.get()) print(que.get())
# 管道相当于生成两个连接对象,一个主进程使用,另外一个传递给子进程使用 # 1:导包 from multiprocessing import Process,Pipe import time # 2:定义函数 def ConnAction(conn): # 获取传递过来的conn连接对象 print("准备发送消息,时间%s"%(time.ctime())) conn.send("土豆土豆,我是地瓜,收到请回答") time.sleep(2) print("准备接收消息,时间%s"%(time.ctime())) responInfo = conn.recv() print(responInfo,time.ctime()) if __name__ == '__main__': # 创建管道对象 par_conn,child_conn=Pipe() # 创建进程 p=Process(target=ConnAction,args=(child_conn,)) p.start() print("主进程,准备接收消息,%s"%(time.ctime())) respons=par_conn.recv() print(respons,time.ctime()) time.sleep(2) print("主进程,准备发送消息,%s"%(time.ctime())) par_conn.send("地瓜地瓜,我是土豆");
# 1:导包 from multiprocessing import Process,Manager #2:定义方法 def manaAction(d,l,n): # 对字典进行操作 d[n]="1" d["2"]=2 # 对列表进行操作 l.append(n) if __name__ == '__main__': # 创建Manager对象中的数据类型 with Manager() as manager: d=manager.dict() l=manager.list(range(5)) p_list=[] # 创建进程 for i in range(0,5): p=Process(target=manaAction,args=(d,l,i)) p.start() p_list.append(p) for res in p_list: res.join() print(d) print(l)
# 1:导入包 from multiprocessing import Process,Lock import time #定义方法 def printPro(l,n): with l: print("Hello,World %s,%s"%(n,time.ctime())) time.sleep(1) if __name__ == '__main__': l=Lock() for i in range(0, 5): p = Process(target=printPro, args=(l,i,)) p.start()
# 1:导包 from multiprocessing import Process,Pool import time # 3:创建方法 def foo(i): time.sleep(1) print(i) return i # 4:创建回调方法 def bar(arg): #回调方法在主函数中执行 print("hello,%s"%arg) if __name__ == '__main__': # 2:创建进程池对象 pool = Pool(5) for i in range(0,30): pool.apply_async(func=foo,args=(i,),callback=bar) pool.close() pool.join()
三 协程
协程是一种非抢占式程序,其本质是一个线程。
优点:1:灭有切换消耗;2:没有锁的概念
缺点:无法使用多核,但是可以通过多进程+协程弥补
# 通过yield来实现 # 1:导包 import time #2:消费者 def Consumer(name): print("准备开始吃包子") while True: newbaozi=yield print("%s吃了包子%s"%(name,newbaozi)) #3:生产者 def Product(): r=con.__next__() r2=con2.__next__() baoziName=1 while True: time.sleep(1) print("生产者,生产了%s和%s包子"%(baoziName,baoziName+1)) con.send(baoziName) con2.send(baoziName+1) baoziName+=2 #主方法 if __name__ == '__main__': #创建两个用户 con=Consumer("张三") con2=Consumer("李四") Product()
from greenlet import greenlet def test1(): print(12) gr2.switch() print(34) gr2.switch() def test2(): print(56) gr1.switch() print(78) gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
# 1:导包 import gevent import requests,time # 记录开始时间 start = time.time() def f(url): # print("Get:%s" %url) reap=requests.get(url) data=reap.text print("%s网址上一共有%s字节"%(url,len(data))) gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'), gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://www.baidu.com/'), gevent.spawn(f, 'https://www.sina.com.cn/'), ]) print("耗时",time.time()-start) f('https://www.python.org/') f('https://www.yahoo.com/') f('https://www.baidu.com/') f('https://www.sina.com.cn/') print("耗时",time.time()-start)