*****Python之进程线程*****
Python之进程线程
Python的threading模块
并发编程:
操作系统:位于底层硬件与应用软件之间的一层。
工作方式:向下管理硬件,向上提供接口。
进程:资源管理单位(容器)
线程:最小执行单位
Python的多线程:由于GIL,导致同一时间,同一时刻,只能有一个线程在运行。
t.join():线程对象t未执行完,会阻塞你的主线程。
全局解释器锁GIL:加在CPython解释器上。
计算密集型:一直在使用CPU
IO:存在大量的IO操作
总结:
对于计算密集型任务:Python的多线程没用
对于IO密集型任务:Python的多线程有用
Python使用多核:开进程,
弊端:开销大,切换复杂
重点:协程+多进程
IO多路复用
线程:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 调用方式1 2 3 # import threading 4 # import time 5 # 6 # def tingge(): 7 # print("听歌") 8 # time.sleep(3) 9 # print("听歌结束") 10 # 11 # def xieboke(): 12 # print("写博客") 13 # time.sleep(5) 14 # print("写博客结束") 15 # 16 # print(time.time()-s) 17 # 18 # s=time.time() 19 # 20 # t1=threading.Thread(target=tingge) 21 # t2=threading.Thread(target=xieboke) 22 # 23 # t1.start() 24 # t2.start() 25 26 27 28 # 调用方式2 29 # import threading 30 # import time 31 # 32 # class MyThread(threading.Thread): 33 # 34 # def __init__(self,num): 35 # threading.Thread.__init__(self) 36 # self.num=num 37 # 38 # def run(self): 39 # print("running on number:%s" %self.num) 40 # time.sleep(3) 41 42 # t1=MyThread(56) 43 # t2=MyThread(78) 44 # 45 # t1.start() 46 # t2.start() 47 # 48 # print("ending")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import threading 2 from time import ctime,sleep 3 import time 4 5 def Music(name): 6 7 print ("Begin listening to {name}. {time}".format(name=name,time=ctime())) 8 sleep(3) 9 print(threading.activeCount()) 10 print(threading.enumerate()) 11 print("end listening {time}".format(time=ctime())) 12 13 14 def Blog(title): 15 16 print ("Begin recording the {title}. {time}".format(title=title,time=ctime())) 17 sleep(5) 18 print('end recording {time}'.format(time=ctime())) 19 20 21 threads = [] 22 23 24 t1 = threading.Thread(target=Music,args=('FILL ME',),name="sub_thread") 25 t2 = threading.Thread(target=Blog,args=('',)) 26 27 threads.append(t1) 28 threads.append(t2) 29 30 if __name__ == '__main__': 31 32 t1.setDaemon(True) # daemon:监听 33 34 for t in threads: 35 36 t.start() 37 38 print ("all over %s" %ctime())
GIL锁:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 3 4 def cal(n): 5 sum=0 6 for i in range(n): 7 sum += i 8 9 s=time.time() 10 11 import threading 12 13 14 t1=threading.Thread(target=cal,args=(50000000,)) 15 t2=threading.Thread(target=cal,args=(50000000,)) 16 17 t1.start() 18 t2.start() 19 t1.join() 20 t2.join() 21 22 # cal(50000000) 23 # cal(50000000) 24 25 print("time",time.time()-s)
JOIN和Daemon:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # import threading 2 # from time import ctime,sleep 3 # import time 4 # 5 # def Music(name): 6 # 7 # print ("Begin listening to {name}. {time}".format(name=name,time=ctime())) 8 # sleep(3) 9 # print("end listening {time}".format(time=ctime())) 10 # 11 # def Blog(title): 12 # 13 # print ("Begin recording the {title}. {time}".format(title=title,time=ctime())) 14 # sleep(5) 15 # print('end recording {time}'.format(time=ctime())) 16 # 17 # 18 # threads = [] 19 # 20 # t1 = threading.Thread(target=Music,args=('FILL ME',)) 21 # t2 = threading.Thread(target=Blog,args=('python',)) 22 # 23 # threads.append(t1) 24 # threads.append(t2) 25 # 26 # if __name__ == '__main__': 27 28 #t2.setDaemon(True) 29 # t2.setDaemon(True) 30 31 # for t in threads: 32 # 33 # t.start() 34 35 # for t in threads: 36 # t.join() 37 38 # t1.start() 39 # t1.join() 40 # t2.start() 41 # t2.join() 42 43 # print ("all over %s" %ctime())
死锁和递归锁(RLock):
RLock内部维护里一个计数器,与同步锁相比,可以多次release和acquire。 加锁是维护公共数据。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import threading 2 import time 3 4 # mutexA = threading.Lock() 5 # mutexB = threading.Lock() 6 7 Rlock=threading.RLock() 8 9 class MyThread(threading.Thread): 10 11 def __init__(self): 12 threading.Thread.__init__(self) 13 14 def run(self): 15 16 self.fun1() 17 self.fun2() 18 19 def fun1(self): 20 21 Rlock.acquire() # 如果锁被占用,则阻塞在这里,等待锁的释放 22 23 print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time())) 24 25 Rlock.acquire() # count=2 26 print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time())) 27 Rlock.release() #count-1 28 29 Rlock.release() #count-1 =0 30 31 32 def fun2(self): 33 Rlock.acquire() # count=1 34 print ("I am %s , get res: %s---%s" %(self.name, "ResB",time.time())) 35 time.sleep(0.2) 36 37 Rlock.acquire() # count=2 38 print ("I am %s , get res: %s---%s" %(self.name, "ResA",time.time())) 39 Rlock.release() 40 41 Rlock.release() # count=0 42 43 44 if __name__ == "__main__": 45 46 print("start---------------------------%s"%time.time()) 47 48 for i in range(0, 10): 49 50 my_thread = MyThread() 51 my_thread.start()
同步锁:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 import threading 3 4 def subNum(): 5 6 global num #在每个线程中都获取这个全局变量 7 # num-=1 8 print("ok") 9 lock.acquire() #上锁 10 temp=num 11 time.sleep(0.1) 12 num =temp-1 # 对此公共变量进行-1操作 13 lock.release() #解锁 14 15 num = 100 #设定一个共享变量 16 thread_list = [] 17 18 lock=threading.Lock() 19 20 for i in range(100): 21 t = threading.Thread(target=subNum) 22 t.start() 23 thread_list.append(t) 24 # t.join() 25 26 for t in thread_list: #等待所有线程执行完毕 27 t.join() 28 29 print('Result: ', num)
反射:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # #继承Thread式创建 2 # 3 # import threading 4 # import time 5 # 6 # class MyThread(threading.Thread): 7 # 8 # def __init__(self,num): 9 # threading.Thread.__init__(self) 10 # self.num=num 11 # 12 # def run(self): 13 # print("running on number:%s" %self.num) 14 # time.sleep(3) 15 # 16 # t1=MyThread(56) 17 # t2=MyThread(78) 18 # 19 # t1.start() 20 # t2.start() 21 # print("ending") 22 import time 23 class Card: 24 bank="工行" 25 def __init__(self,card_number,own_name,money,card_date): 26 self.card_number=card_number 27 self.own_name=own_name 28 self.money=money 29 self.card_date=card_date 30 def view(self): 31 print("账户信息,%s欢迎登录"%(self.bank),self.card_number,self.own_name,self.money,self.card_date) 32 def take(self,take_money): 33 mum=self.money-take_money 34 print("你一共取了%s,余额为%s",take_money,mum) 35 36 c1=Card("6220144549585","lzh",10000,time.asctime()) 37 # print(c1.__dict__)#为什么我们可以用字符串操作类下的数据属性和函数属性,因为它们都是以字典的形式存在 38 print(hasattr(c1,"bank"))#hasattr,以字符串的形式获取类下的属性名,如果存在返回真 39 print(getattr(c1,"take"))#getattr,得到类下的一个函数属性,如果存在返回一个绑定的函数方法 40 print(getattr(c1,"take1","没有这个方法"))#getattr,如果没有指定的属性,则报错,getattr还可以添加一个自定义的报错值 41 #当添加这个值后,getattr方法会返回这个定义值 42 setattr(c1,"addr","沙河分行")#该方法添加类的数据属性 43 setattr(c1,"bank","爱存不存")#此处可以修改类中的数据属性值 44 print(c1.bank) 45 print(c1.addr) 46 delattr(c1,"bank") 47 print(c1.__dict__) 48 #简单的应用示例,我们可以通过用户输入字符串的形式确定类这个对象中是否有这个操作, 49 # 如果有,就执行,显示结果,没有就不做任何操作 50 if hasattr(c1,"view"): 51 func=getattr(c1,"view") 52 res=func() 53 print(res) 54 else: 55 pass
event对象:理解为标识位,True和False就好。False将阻塞线程。用set方法,event.set()将event的False状态改为True。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import threading 2 import time 3 import logging 4 5 logging.basicConfig(level=logging.DEBUG, format='(%(threadName)-10s) %(message)s',) 6 7 8 def worker(event): 9 logging.debug('Waiting for redis ready...') 10 11 while not event.isSet(): 12 logging.debug("wait.......") 13 event.wait(3) # if flag=False阻塞,等待flag=true继续执行 14 15 16 logging.debug('redis ready, and connect to redis server and do some work [%s]', time.ctime()) 17 time.sleep(1) 18 19 def main(): 20 21 readis_ready = threading.Event() # flag=False 22 t1 = threading.Thread(target=worker, args=(readis_ready,), name='t1') 23 t1.start() 24 25 t2 = threading.Thread(target=worker, args=(readis_ready,), name='t2') 26 t2.start() 27 28 logging.debug('first of all, check redis server, make sure it is OK, and then trigger the redis ready event') 29 30 time.sleep(6) # simulate the check progress 31 readis_ready.set() # flag=Ture 32 33 34 if __name__=="__main__": 35 main()
信号量:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import threading 2 import time 3 4 semaphore = threading.Semaphore(5) 5 6 def func(): 7 8 semaphore.acquire() 9 print (threading.currentThread().getName() + ' get semaphore') 10 time.sleep(2) 11 semaphore.release() 12 13 14 for i in range(20): 15 t1 = threading.Thread(target=func) 16 t1.start()
进程模块:multiprocessing
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #coding:utf8 2 from multiprocessing import Process 3 import time 4 5 def counter(): 6 i = 0 7 for _ in range(40000000): 8 i = i + 1 9 10 return True 11 12 def main(): 13 14 l=[] 15 start_time = time.time() 16 # 17 # for _ in range(2): 18 # t=Process(target=counter) 19 # t.start() 20 # l.append(t) 21 # #t.join() 22 # 23 # for t in l: 24 # t.join() 25 26 # counter() 27 # counter() 28 29 end_time = time.time() 30 print("Total time: {}".format(end_time - start_time)) 31 32 if __name__ == '__main__': 33 34 main()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # from multiprocessing import Process 2 # 3 # 4 # import time 5 # 6 # 7 # def f(name): 8 # 9 # print('hello', name,time.ctime()) 10 # time.sleep(1) 11 # 12 # if __name__ == '__main__': 13 # p_list=[] 14 # 15 # for i in range(3): 16 # p = Process(target=f, args=('alvin:%s'%i,)) 17 # p_list.append(p) 18 # p.start() 19 # 20 # 21 # # for i in p_list: 22 # # p.join() 23 # 24 # print('end')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from multiprocessing import Process 2 import os 3 import time 4 5 def info(name): 6 7 print("name:",name) 8 print('parent process:', os.getppid()) 9 print('process id:', os.getpid()) 10 print("------------------") 11 12 13 def foo(name): 14 15 info(name) 16 time.sleep(50) 17 18 if __name__ == '__main__': 19 20 info('main process line') 21 22 23 p1 = Process(target=info, args=('alvin',)) 24 p2 = Process(target=foo, args=('egon',)) 25 p1.start() 26 p2.start() 27 28 p1.join() 29 p2.join() 30 31 print("ending") 32 time.sleep(100)
协程:
协程的优点,由于单线程,所以就不用再切换。
不在有锁的概念。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import time 2 3 # 可以实现并发 4 5 6 def consumer(): 7 8 r = '' 9 while True: 10 11 n = yield r 12 if not n: 13 return 14 print('[CONSUMER] ←← Consuming %s...' % n) 15 time.sleep(1) 16 r = '200 OK' 17 18 def produce(c): 19 20 next(c) 21 n = 0 22 while n < 5: 23 n = n + 1 24 print('[PRODUCER] →→ Producing %s...' % n) 25 26 cr = c.send(n) 27 28 print('[PRODUCER] Consumer return: %s' % cr) 29 30 c.close() 31 32 if __name__=='__main__': 33 34 c = consumer() 35 produce(c)
greenlet模块:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # from greenlet import greenlet 2 # 3 # 4 # def test1(): 5 # print(12) 6 # 7 # gr2.switch() 8 # print(34) 9 # gr2.switch() 10 # 11 # 12 # def test2(): 13 # print(56) 14 # gr1.switch() 15 # print(78) 16 # 17 # 18 # gr1 = greenlet(test1) 19 # gr2 = greenlet(test2) 20 # 21 # gr1.switch() 22 23 24 #gevent模块 25 26 # import gevent 27 # import time 28 # 29 # def foo(): 30 # print("running in foo") 31 # gevent.sleep(2) 32 # print("switch to foo again") 33 # 34 # def bar(): 35 # print("switch to bar") 36 # gevent.sleep(5) 37 # print("switch to bar again") 38 # 39 # start=time.time() 40 # 41 # gevent.joinall( 42 # [gevent.spawn(foo), 43 # gevent.spawn(bar)] 44 # ) 45 # 46 # print(time.time()-start) 47 48 from gevent import monkey 49 monkey.patch_all() 50 51 import gevent 52 from urllib import request 53 import time 54 55 def f(url): 56 print('GET: %s' % url) 57 resp = request.urlopen(url) 58 data = resp.read() 59 print('%d bytes received from %s.' % (len(data), url)) 60 61 start=time.time() 62 63 # gevent.joinall([ 64 # gevent.spawn(f, 'https://itk.org/'), 65 # gevent.spawn(f, 'https://www.github.com/'), 66 # gevent.spawn(f, 'https://zhihu.com/'), 67 # ]) 68 69 f('https://itk.org/') 70 f('https://www.github.com/') 71 f('https://zhihu.com/') 72 73 74 print(time.time()-start)
test:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # class A: 2 # def __fa(self): 3 # print('from A') 4 # def test(self): 5 # self.__fa() #_A__fa 6 # 7 # class B(A): 8 # def __fa(self): 9 # print('from B') 10 # 11 # b=B() 12 # b.test() 13 14 15 16 17 #用来计算类被实例化的次数 18 # def get_no_(cls_obj): 19 # return cls_obj.times_inst 20 #通常情况下,类实例是解释器自动调用类的__init__()来构造的,通常情况下,类实例是解释器自动调用类的__init__()来构造的 21 class Exm_cls: 22 #实例化次数的初始值为0 23 times_inst = 0 24 #类被实例化一次,就+1 25 def __init__(self): 26 Exm_cls.times_inst +=1 27 #在内部定义这个函数,并且把他绑定到类 28 @classmethod 29 def get_no_(cls): 30 return cls.times_inst 31 @staticmethod 32 def show_type(): 33 fn = classmethod(Exm_cls.get_no_) 34 print(type(fn)) 35 exm1 = Exm_cls() 36 exm2 = Exm_cls() 37 print(Exm_cls.get_no_()) 38 print(Exm_cls.show_type()) 39 # print(get_no_(Exm_cls))