week10-线程及相关线程属性
开启线程的方式一:使用替换threading模块提供的Thread
from threading import Thread from multiprocessing import Process def task(): print('is running') if __name__ == '__main__': t=Thread(target=task,) # t=Process(target=task,) t.start() print('主')
开启线程的方式二:自定义类,继承Thread
from threading import Thread from multiprocessing import Process class MyThread(Thread): def __init__(self,name): super().__init__() self.name=name def run(self): print('%s is running' %self.name) if __name__ == '__main__': t=MyThread('egon') # t=Process(target=task,) t.start() print('主')
线程和进程的pid
from threading import Thread from multiprocessing import Process import os def task(): print('%s is running' %os.getpid()) if __name__ == '__main__': # t1=Thread(target=task,) # t2=Thread(target=task,) t1=Process(target=task,) t2=Process(target=task,) t1.start() t2.start() print('主',os.getpid())
线程共享同一进程内的资源
from threading import Thread from multiprocessing import Process n=100 def work(): global n n=0 if __name__ == '__main__': # p=Process(target=work,) # p.start() # p.join() # print('主',n) t=Thread(target=work,) t.start() t.join() print('主',n)
多线程共享同一进程内地址空间的练习
from threading import Thread msg_l=[] format_l=[] def talk(): while True: msg=input('>>: ').strip() msg_l.append(msg) def format(): while True: if msg_l: data=msg_l.pop() format_l.append(data.upper()) def save(): while True: if format_l: data=format_l.pop() with open('db.txt','a') as f: f.write('%s\n' %data) if __name__ == '__main__': t1=Thread(target=talk) t2=Thread(target=format) t3=Thread(target=save) t1.start() t2.start() t3.start()
Thread对象其他相关的属性或方法
from threading import Thread,activeCount,enumerate,current_thread import time def task(): print('%s is running' %current_thread().getName()) time.sleep(2) if __name__ == '__main__': t=Thread(target=task,) t.start() t.join() print(t.is_alive()) print(t.getName()) print(enumerate()) print('主') print(activeCount()) current_thread的用法 from threading import Thread,activeCount,enumerate,current_thread from multiprocessing import Process import time def task(): print('%s is running' %current_thread().getName()) time.sleep(2) if __name__ == '__main__': p=Process(target=task) p.start() print(current_thread()) from threading import Thread,activeCount,enumerate,current_thread from multiprocessing import Process import time def task(): print('%s is running' %current_thread().getName()) time.sleep(2) if __name__ == '__main__': t1=Thread(target=task) t2=Thread(target=task) t3=Thread(target=task) t1.start() t2.start() t3.start() print(current_thread()) #强调:主线程从执行层面上代表了其所在进程的执行过程
守护线程
# 先看:守护进程 from multiprocessing import Process import time def task1(): print('123') time.sleep(1) print('123done') def task2(): print('456') time.sleep(10) print('456done') if __name__ == '__main__': p1=Process(target=task1) p2=Process(target=task2) p1.daemon = True p1.start() p2.start() print('主') #再看:守护线程 from threading import Thread import time def task1(): print('123') time.sleep(10) print('123done') def task2(): print('456') time.sleep(1) print('456done') if __name__ == '__main__': t1=Thread(target=task1) t2=Thread(target=task2) t1.daemon=True t1.start() t2.start() print('主')
GIT全局解释器锁
from threading import Thread n=100 def task(): print('is running') if __name__ == '__main__': t1=Thread(target=task,) t2=Thread(target=task,) t3=Thread(target=task,) # t=Process(target=task,) t1.start() t2.start() t3.start() print('主')
线程的互斥锁
from threading import Thread,Lock import time n=100 def work(): global n mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release() if __name__ == '__main__': mutex=Lock() l=[] start=time.time() for i in range(100): t=Thread(target=work) l.append(t) t.start() for t in l: t.join() print('run time:%s value:%s' %(time.time()-start,n))
互斥锁与join的区别,join是整个线程,互斥锁是区域
from threading import Thread,Lock import time n=100 def work(): time.sleep(0.05) global n temp=n time.sleep(0.1) n=temp-1 if __name__ == '__main__': start=time.time() for i in range(100): t=Thread(target=work) t.start() t.join() print('run time:%s value:%s' %(time.time()-start,n)) #互斥锁 from threading import Thread,Lock import time n=100 def work(): time.sleep(0.05) global n mutex.acquire() temp=n time.sleep(0.1) n=temp-1 mutex.release() if __name__ == '__main__': mutex=Lock() l=[] start=time.time() for i in range(100): t=Thread(target=work) l.append(t) t.start() for t in l: t.join() print('run time:%s value:%s' %(time.time()-start,n))
GIL与多线程性能讨论
#多进程: #优点:可以利用多核优势 #缺点:开销大 #多线程: #优点:开销小 #缺点:不能利用多核优势 from threading import Thread from multiprocessing import Process import time #计算密集型 def work(): res=1 for i in range(100000000): res+=i if __name__ == '__main__': p_l=[] start=time.time() for i in range(4): # p=Process(target=work) #6.7473859786987305 p=Thread(target=work) #24.466399431228638 p_l.append(p) p.start() for p in p_l: p.join() print(time.time()-start) from threading import Thread from multiprocessing import Process import time #IO密集型 def work(): time.sleep(2) if __name__ == '__main__': p_l=[] start=time.time() for i in range(400): # p=Process(target=work) #12.104692220687866 p=Thread(target=work) #2.038116455078125 p_l.append(p) p.start() for p in p_l: p.join() print(time.time()-start)
死锁与递归锁
#死锁现象 from threading import Thread,Lock,RLock import time mutexA=Lock() mutexB=Lock() class Mythread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print('\033[45m%s 抢到A锁\033[0m' %self.name) mutexB.acquire() print('\033[44m%s 抢到B锁\033[0m' %self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print('\033[44m%s 抢到B锁\033[0m' %self.name) time.sleep(1) mutexA.acquire() print('\033[45m%s 抢到A锁\033[0m' %self.name) mutexA.release() mutexB.release() if __name__ == '__main__': for i in range(20): t=Mythread() t.start() #递归锁 from threading import Thread,Lock,RLock import time mutex=RLock() class Mythread(Thread): def run(self): self.f1() self.f2() def f1(self): mutex.acquire() print('\033[45m%s 抢到A锁\033[0m' %self.name) mutex.acquire() print('\033[44m%s 抢到B锁\033[0m' %self.name) mutex.release() mutex.release() def f2(self): mutex.acquire() print('\033[44m%s 抢到B锁\033[0m' %self.name) time.sleep(1) mutex.acquire() print('\033[45m%s 抢到A锁\033[0m' %self.name) mutex.release() mutex.release() if __name__ == '__main__': for i in range(20): t=Mythread() t.start()
信号量
from threading import Thread,current_thread,Semaphore import time,random sm=Semaphore(5) def work(): sm.acquire() print('%s 上厕所' %current_thread().getName()) time.sleep(random.randint(1,3)) sm.release() if __name__ == '__main__': for i in range(20): t=Thread(target=work) t.start()
事件Event
from threading import Thread,current_thread,Event import time event=Event() def conn_mysql(): count=1 while not event.is_set(): if count > 3: raise ConnectionError('链接失败') print('%s 等待第%s次链接mysql' %(current_thread().getName(),count)) event.wait(0.5) count+=1 print('%s 链接ok' % current_thread().getName()) def check_mysql(): print('%s 正在检查mysql状态' %current_thread().getName()) time.sleep(1) event.set() if __name__ == '__main__': t1=Thread(target=conn_mysql) t2=Thread(target=conn_mysql) check=Thread(target=check_mysql) t1.start() t2.start() check.start()
定时器
from threading import Timer def hello(n): print("hello, world",n) t = Timer(3, hello,args=(11,)) t.start() # after 1 seconds, "hello, world" will be printed
线程queue
import queue q=queue.Queue(3) #队列:先进先出 q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) q=queue.LifoQueue(3) #堆栈:后进先出 q.put(1) q.put(2) q.put(3) print(q.get()) print(q.get()) print(q.get()) q=queue.PriorityQueue(3) #数字越小优先级越高 q.put((10,'data1')) q.put((11,'data2')) q.put((9,'data3')) print(q.get()) print(q.get()) print(q.get())
进程池与线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor import os,time,random def work(n): print('%s is running' %os.getpid()) time.sleep(random.randint(1,3)) return n**2 if __name__ == '__main__': p=ProcessPoolExecutor() # objs=[] # for i in range(10): # obj=p.submit(work,i) # objs.append(obj) # p.shutdown() # for obj in objs: # print(obj.result()) obj=p.map(work,range(10)) p.shutdown() print(list(obj)) from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor from threading import current_thread import os,time,random def work(n): print('%s is running' %current_thread().getName()) time.sleep(random.randint(1,3)) return n**2 if __name__ == '__main__': p=ThreadPoolExecutor() objs=[] for i in range(21): obj=p.submit(work,i) objs.append(obj) p.shutdown() for obj in objs: print(obj.result()) #进程池 import requests #pip3 install requests import os,time from multiprocessing import Pool from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor def get_page(url): print('<%s> get :%s' %(os.getpid(),url)) respone = requests.get(url) if respone.status_code == 200: return {'url':url,'text':respone.text} def parse_page(obj): dic=obj.result() print('<%s> parse :%s' %(os.getpid(),dic['url'])) time.sleep(0.5) res='url:%s size:%s\n' %(dic['url'],len(dic['text'])) #模拟解析网页内容 with open('db.txt','a') as f: f.write(res) if __name__ == '__main__': # p=Pool(4) p=ProcessPoolExecutor() urls = [ 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', ] for url in urls: # p.apply_async(get_page,args=(url,),callback=parse_page) p.submit(get_page,url).add_done_callback(parse_page) p.shutdown() print('主进程pid:',os.getpid()) # 线程池 import requests #pip3 install requests import os,time,threading from multiprocessing import Pool from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor def get_page(url): print('<%s> get :%s' %(threading.current_thread().getName(),url)) respone = requests.get(url) if respone.status_code == 200: return {'url':url,'text':respone.text} def parse_page(obj): dic=obj.result() print('<%s> parse :%s' %(threading.current_thread().getName(),dic['url'])) time.sleep(0.5) res='url:%s size:%s\n' %(dic['url'],len(dic['text'])) #模拟解析网页内容 with open('db.txt','a') as f: f.write(res) if __name__ == '__main__': # p=Pool(4) p=ThreadPoolExecutor(3) urls = [ 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com', ] for url in urls: # p.apply_async(get_page,args=(url,),callback=parse_page) p.submit(get_page,url).add_done_callback(parse_page) p.shutdown() print('主进程pid:',os.getpid())
并发编程重要的知识点
1 生产者消费者模型
2 进程池线程池
3 回调函数
4 GIL全局解释器锁
志不强者智不达
浙公网安备 33010602011771号