一、守护进程应用实例
import time
import random
from multiprocessing import Process,JoinableQueue
def consumer(name,q):
while True:
res=q.get()
if res is None:break
time.sleep(random.randint(1,3))
print(' 33[46m消费者===》%s 吃了 %s 33[0m' %(name,res))
q.task_done()
def producer(name,q,food):
for i in range(5):
time.sleep(random.randint(1,2))
res='%s%s' %(food,i)
q.put(res)
print(' 33[45m生产者者===》%s 生产了 %s 33[0m' %(name,res))
if __name__ == '__main__':
#1、共享的盆
q=JoinableQueue()
#2、生产者们
p1=Process(target=producer,args=('egon',q,'包子'))
p2=Process(target=producer,args=('刘清政',q,'泔水'))
p3=Process(target=producer,args=('杨军',q,'米饭'))
#3、消费者们
c1=Process(target=consumer,args=('alex',q))
c2=Process(target=consumer,args=('梁书东',q))
c1.daemon=True
c2.daemon=True
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
# 确定生产者确确实实已经生产完毕
p1.join()
p2.join()
p3.join()
# 在生产者生产完毕后,拿到队列中元素的总个数,然后直到元素总数变为0,q.join()这一行代码才算运行完毕
q.join()
#q.join()一旦结束就意味着队列确实被取空,消费者已经确确实实把数据都取干净了
print('主进程结束')
二、线程
1、什么是线程
线程指的是一条流水线的工作过程
进程根本就不是一个执行单位,进程其实是一个资源单位
一个进程内自带一个线程,线程才是执行单位
2、进程VS线程
1、同一进程内的线程们共享该进程内资源,不同进程内的线程资源肯定是隔离的
2、创建线程的开销比创建进程要小的多
注:线程因资源消耗较少所以开启速度较快
开启线程方式一:
from multiprocessing import Process
from threading import Thread
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
if __name__ == '__main__':
t=Thread(target=task,args=('egon',))
t.start()
print('主线程')
开启线程方式二:
from multiprocessing import Process
from threading import Thread
import time
class MyThread(Thread):
def run(self):
print('%s is running' %self.name)
time.sleep(3)
if __name__ == '__main__':
t=MyThread()
t.start()
print('主线程')
线程对象的其他方法:
from threading import Thread,current_thread,active_count,enumerate
import time,os
def task():
print('%s is running' %current_thread().name) #打印线程名
time.sleep(3)
if __name__ == '__main__':
t1=Thread(target=task,name='第一个线程') #为线程命名
t2=Thread(target=task,)
t3=Thread(target=task,)
t1.start()
t2.start()
t3.start()
# print(t1.is_alive())
print(active_count()) #计算总共运行了多少个线程
print(enumerate()) #列出所有正在运行的线程
print('主线程',current_thread().name)
守护线程:
示例代码:
from threading import Thread
import time
def foo():
print(123)
time.sleep(5)
print("end123")
def bar():
print(456)
time.sleep(3)
print("end456")
if __name__ == '__main__':
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------")
与进程不同守护线程结束运行时间为其它所有进程结束之后才会执行
三、递归锁
死锁就是在程序中有两个或者两个以上的互斥锁,互相锁死导致程序卡死,在程序中应尽量避免使用互斥锁。
递归锁也是解决死锁问题一种方法,在程序中线程每次拿到锁都会把所有锁计数加一,每次丢掉锁计数减一,
只要锁的计数不为零别的程序就无法加锁
from threading import Thread,Lock,RLock
import time
mutexA=mutexB=RLock()
class MyThread(Thread):
def run(self):
self.f1()
self.f2()
def f1(self):
mutexA.acquire()
print('%s 拿到了A锁' %self.name)
mutexB.acquire()
print('%s 拿到了B锁' %self.name)
mutexB.release()
mutexA.release()
def f2(self):
mutexB.acquire()
print('%s 拿到了B锁' %self.name)
time.sleep(0.1)
mutexA.acquire()
print('%s 拿到了A锁' %self.name)
mutexA.release()
mutexB.release()
if __name__ == '__main__':
for i in range(10):
t=MyThread()
t.start()
print('主')
三、信号量
互斥锁 在同时只允许一个人更改数据而信号量Semaphore 则是允许指定数量的线程更改数据,指定多少个线程可以更改,
后续线程只能等待前面线程释放后才能加锁。
示例代码:
from threading import Thread,Semaphore,current_thread
import time,random
sm=Semaphore(5)
def go_wc():
sm.acquire()
print('%s 上厕所ing' %current_thread().getName())
time.sleep(random.randint(1,3))
sm.release()
if __name__ == '__main__':
for i in range(23):
t=Thread(target=go_wc)
t.start()