python线程
Posted 岐岐卡卡西
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python线程相关的知识,希望对你有一定的参考价值。
- 子类继承父类的初始化方法
class student1(student): #student为父类,父类有name,age,stno这些属性 def __init__(self,name,age,stno,addr): #在父类的基础上加了一个addr属性 student.__init(self,name,age,stno) #显示调用父类的初始化方法 self.addr=addr #不在父类的属性自行初始化
class myThread(threading.Thread): #继承父类Thread def __init__(self,url): super().__init__() #通过super()关键字显示调用父类 self.url=url
创建线程的两种方法
- 通过Thread类构造器来创建线程
def get_web(url): #定义创建线程之后要执行的方法,即是线程的执行体 headers = { ‘User-Agent‘:‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘ } req = urllib.request.Request(url,headers=headers) resp = urllib.request.urlopen(req) print(resp.read().decode()[:50]) if __name__==‘__main__‘: t=threading.Thread(target=get_web,args=(url,)) #使用Thread类的构造器来创建线程,在线程参数中规定线程的执行方法和方法的参数 t.start() #运行线程 t.join() #阻塞线程,执行主程序
- 通过继承Thread类创建线程
class myThread(threading.Thread) #定义类来继承Thread,创建新线程 def __init__(self,url): #定义新类的初始化方法 super().__init__() #显示调用父类的初始化方法 self.url=url def run(self) #定义父类中的run方法,表示线程的执行过程 headers = { ‘User-Agent‘:‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘ } req = urllib.request.Request(self.url,headers=headers) resp = urllib.request.urlopen(req) print(resp.read().decode()[:50]) if __name__==‘__main__‘: t=myThread(url) #初始化新定义的线程,传递新线程所需的各种参数 t.start() #运行线程 t.join() #阻塞主程序,执行线程
全局解释器锁GIL。当前线程执行I/O操作时,会释放GIL。当前线程执行超过100字节码,也会释放GIL。
import threading n = 0 lock = threading.Lock() def add(): for i in range(1000000): with lock: global n n += 1 def minus(): for i in range(1000000): with lock: global n n -= 1 if __name__==‘__main__‘: t1 = threading.Thread(target=add) t2 = threading.Thread(target=minus) t1.start() t2.start() t1.join() t2.join() print(n) #最后执行结果还是0,加入了锁
使用Queue,消息队列来实现线程间的通信
import threading import time from queue import Queue def produce(q): kind=(‘猪肉‘,‘白菜‘,‘豆沙‘) for i in range(3): print(threading.current_thread().name,‘包子生产者开始生产包子‘) time.sleep(1) q.put(kind[i%3]) #生产者生产后,放入一个包子到消息队列 print(threading.current_thread().name,‘包子生产者生产完包子‘) def consume(q): while True: print(threading.current_thread().name,‘消费者准备吃包子‘) time.sleep(1) t=q.get() #get方法是一个阻塞方法,如果消息队列中没有包子,就会阻塞当前线程 print(‘消费者吃了{}包子‘.format(t)) if __name__==‘__main__‘: q=Queue(maxsize=1) threading.Thread(target=produce,args=(q,)).start() #启动两个生产者线程 threading.Thread(target=produce,args=(q,)).start() threading.Thread(target=consume,args=(q,)).start() #启动一个消费者线程 #执行流程 #先启动三个线程分别执行到线程中的一部分 # 包子生产者1开始生产包子 # 包子生产者2开始生产包子 # 消费者准备吃包子 #此时消息队列中没有包子,生产者1执行剩余部分后,又循环回到头部重新生产包子 # 包子生产者1生产完包子 # 包子生产者1开始生产包子 #此时,消息队列中有包子,消费者开始消费 # 消费者吃了什么包子 #消费者消费完包子后,消息队列中没有包子,生产者2开始生产包子 # 包子生产者2生产完包子 # 包子生产者2开始生产包子 #生产者2生产包子后,消息队列中有包子,消费者吃完包子后又回到循环等待包子 # 消费者吃了什么包子 # 消费者准备吃包子 #此后,生产者1又重新开始生产包子,消费者消费包子,生产者2开始生产包子,消费者消费包子。直到两个生产者都生产完3个包子后,消息队列中没有包子,结束执行。
多进程的实现和多线程大体相同。
多线程具有效率高,耗费资源少,所以非常适合I/O密集型的作业,比如文件读取,爬虫程序。这些程序主要的时间消耗集中在等待时间,多线程就非常适合。多线程缺点就是稳定性差,一个线程崩溃,其余线程也会受到影响。
多进程稳定性高,进程之间互不干扰。所以非常适合计算密集型的作业。多进程缺点耗费计算机大量资源。
以上是关于python线程的主要内容,如果未能解决你的问题,请参考以下文章
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段