python进程、线程

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

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()

输出结果如下:

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

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()

输出结果如下:

在进行出入库操作时,多线程并发时,会导致数据丢失问题。我们写一段代码,库存值为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()

输入结果如下:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值