python进程、线程

系统 1981 0

为什么编程的时候要使用进程、线程、协程?使用它们是为了进行多并发编程。那么为什么要进行多并发编程?因为多并发编程可以减少程序运行的时间,让用户获得更好的体验。

1.进程

概念:操作系统执行程序分配存储空间的最小单位。一个CPU只能同时处理一个进程。python实现多进程,使用multiprocessing模块的Process类来创建进程。具体代码如下:

            
              from multiprocessing import Process
from os import getpid
import time
from random import randint

def download(filename):
    """
    定义一个下载文件的方法
    :param filename:要下载的文件名
    :return:
    """
    task = randint(8, 15)
    time.sleep(task)
    print("下载文件:%s,花费%s秒"%(filename,task))

def main():
    #记录开始下载时间
    start = time.time()
    #创建一个进程,target为进程要执行的方法,args是一个元组,为调用该方法要传入的参数。
    p1 = Process(target=download,args=("python自动化测试.pdf",))
    #启动进程
    p1.start()
    p2 = Process(target=download,args=("测试技巧.pdf",))
    p2.start()
    #执行进程并等待进程执行结束
    p1.join()
    p2.join()
    #记录下载完成时间
    end = time.time()
    #输出下载总耗时
    print("下载总耗时%.2f秒"%(end-start))

if __name__  == "__main__":
    main()
            
          

输出结果如下:

python进程、线程_第1张图片

使用多进程的编程的好处是可以大大提高代码的执行效率,但是多进程存在一个问题,进程之前的通信比较复杂,实现起来会占用较大的资源,此时我们引入线程的来解决这个问题。

2.线程

一个进程可以包含多个线程,同一进程中的每个线程的信息是可以进行共享的。python使用threading模块的Thread类来创建新的线程。python的类是可以继承的,我们创建类时可以继承Thread类。具体代码如下:

            
              from threading import Thread
from random import randint
import time

#创建Download类,继承Thread类
class Download(Thread):

    def __init__(self, filename):
        super().__init__()
        self._filename = filename

    def run(self):
        task = randint(8, 13)
        time.sleep(task)
        print("下载文件:%s,花费%s秒"%(self._filename,task))

    def close(self):
        print("3sdf%s"%self._filename)

def main():
    start = time.time()
    t1 = Download("python自动化测试.pdf")
    #执行t1.start时,会运行run方法
    t1.start()
    t2 = Download("测试技巧.pdf")
    t2.start()
    t1.join()
    t2.join()
    end = time.time()
    print("下载完成,共耗时%.2f"%(end-start))

if __name__ == "__main__":
    main()
            
          

输出结果如下:

python进程、线程_第2张图片

在进行出入库操作时,多线程并发时,会导致数据丢失问题。我们写一段代码,库存值为100,启动50个线程同时进行入库操作,所有线程入库结束后。理论上最终的库存值为150。具体代码如下:

            
              from threading import Thread
from random import randint
import time

class Repertory(object):
    "创建仓库类"
    def __init__(self):
        #初始化仓库数量
        self._initialize_number = 100

    def add_number(self,number):
        #入库操作
        new_number = number+self._initialize_number
        #模拟入库时间
        time.sleep(0.01)
        #更新仓库库存
        self._initialize_number = new_number
    @property
    def number(self):
        #返回仓库库存数量
        return self._initialize_number


class AddNumberThread(Thread):

    def __init__(self, repertory, number):
        """

        :param repertory: 仓库对象
        :param number: 新增库存数量
        """
        super().__init__()
        self._repertory = repertory
        self._number = number

    def run(self):
        self._repertory.add_number(number=self._number)


def main():
    repertory = Repertory()
    threads = []
    #创建50个线程进行入库操作
    for _ in range(50):
        t = AddNumberThread(repertory=repertory,number=1)
        threads.append(t)
        t.start()
    #等待所有线程入库结束
    for thread in threads:
        thread.join()
    #打印最终的库存数
    print("仓库库存数%s"%repertory.number)

if __name__ == "__main__":
    main()
            
          

输出结果如下:

运行结果与我们想象中的完全不一样,因为大部分线程启动的时候,self._initialize_number都等于100,要解决这个问题,就需要用到线程锁。在代码中加入锁,修改后的代码如下:

            
              from threading import Thread, Lock
import time

class Repertory(object):
    "创建仓库类"
    def __init__(self):
        #初始化仓库数量
        self._initialize_number = 100
        #定义锁
        self._lock = Lock()

    def add_number(self,number):
        #拿到锁才能执行下面代码
        self._lock.acquire()
        try:
            #入库操作
            new_number = number+self._initialize_number
            #模拟入库时间
            time.sleep(0.01)
            #更新仓库库存
            self._initialize_number = new_number
        finally:
            #代码执行完成后,释放锁
            self._lock.release()
    @property
    def number(self):
        #返回仓库库存数量
        return self._initialize_number


class AddNumberThread(Thread):

    def __init__(self, repertory, number):
        """

        :param repertory: 仓库对象
        :param number: 新增库存数量
        """
        super().__init__()
        self._repertory = repertory
        self._number = number

    def run(self):
        self._repertory.add_number(number=self._number)


def main():
    repertory = Repertory()
    threads = []
    #创建50个线程进行入库操作
    for _ in range(50):
        t = AddNumberThread(repertory=repertory,number=1)
        threads.append(t)
        t.start()
    #等待所有线程入库结束
    for thread in threads:
        thread.join()
    #打印最终的库存数
    print("仓库库存数%s"%repertory.number)

if __name__ == "__main__":
    main()
            
          

输入结果如下:


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论