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线程的主要内容,如果未能解决你的问题,请参考以下文章

python threading超线程使用简单范例的代码

[Python3] 043 多线程 简介

newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段

python中的多线程和多进程编程

常用python日期日志获取内容循环的代码片段

多线程 Thread 线程同步 synchronized