python中多进程与多线程的用法及场景分析

发布时间:2022-01-04 17:03:28 作者:柒染
来源:亿速云 阅读:186

python中多进程与多线程的用法及场景分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

【写在前面】

        刚开始学习Python 并发查询或者并发读写时,看到大神们说,多线程是python的鸡肋,要学就学多进程。好吧,我连多线程怎么写都不知道呢。

        因此,就写了以下的示例代码。代码目的是将test.txt文件中的内容,以并发的方式(多线程/多进程)进行写入新文件中,以此来验证两种并发方式的效率。

【示例代码】

# coding=utf-8# @Auther : "鹏哥贼优秀"# @Date : 2019/8/10# @Software : PyCharm 
from multiprocessing import Poolimport timeimport threading
# 多进程的写数据方法def writedata(content):    with open("new1.txt", "a") as f:        f.writelines(content)        # 定义自己的多线程继承类class myThread(threading.Thread):    # 声明myThread是多线程的继承类    def __init__(self, content):        threading.Thread.__init__(self)        self.content = content        # 多线程运行的内容    def run(self):        threadingLock = threading.Lock()        threadingLock.acquire()        self.my_writedata(self.content)        threadingLock.release()            # 多线程的写数据方法    def my_writedata(self, content):        with open("new2.txt", "a") as f:            f.writelines(content)
if __name__ == "__main__":    # 创建一个test.txt,用于数据读取后的写入    with open("test.txt","w")as f_w:        for i in range(1000):            f_w.write(str(i)+"\n")    # 多进程读写    print("开始计时(多进程写入)")    t0 = time.time()    with open("test.txt", "r", encoding="utf-8")as f:        content = f.readlines()    pool = Pool(processes=4)    pool.map_async(writedata(content), range(len(content)))    pool.close()    pool.join()    t1 = time.time()    print("完成时间为:{0}".format(t1 - t0))    # 多线程读写    print("开始计时(多线程写入)")    t2 = time.time()    with open("test.txt", "r", encoding="utf-8")as f:        content = f.readlines()    threads = []    threadnum = 4    eline = len(content) // threadnum    for i in range(threadnum):        threadtemp = myThread(content[i * eline:(i + 1) * eline])        threadtemp.start()        threads.append(threadtemp)    for i in threads:        i.join()    t3 = time.time()    print("完成时间为:{0}".format(t3 - t2))

【效果】

python中多进程与多线程的用法及场景分析

(第一个是多进程,我开始的时候打错字了。)

【知识点】

1、多进程 代码流程:

(1)创建进程池,并明确进程数。这里我用的是4个进程,是因为我本地PC机的CPU核是4个。查询方法:

multiprocessing.cpu_count() 即可知道核数了

(2)将具体要执行的方法加入到进程池的异常(map_async)处理中。当然也可以用map方法。其中,map_async方法里需要 2个参数,一个是具体要执行的函数,一个是表示循环执行的次数,类型是个list。示例代码中,因为每次wirtedata是只写了content的一行,因此一共要写len(content)次

(3)最后就是进程池后的关闭,并且在子进程关闭后,主程序才继续往下执行。join()方法无论 是对多线程不是多进程,用途是一样的。

从代码实现上,个人觉得多进程流程简单明了,并且各进程之间写数据是顺序的,不会像多线程因为GIL的随机问题导致进程顺序混乱的问题。但是唯一的问题是,写时间是有点长。

2、多线程代码流程:

       本文采用的是继承threading类的方法,即需要重构run方法。个人觉得这种方式,层次更加清晰,而且能根据自己的目的灵活重构run方法。下面重点介绍这种方法。

(1)定义一个继承threading类的对象,然后重构run方法。其中run方法,需要考虑到锁的问题。为什么要考虑锁呢?因为存在多个线程同时写文件的情况,如果不加锁,就会出现多个线程同时写相同一条数据的情况,导致出现脏数据。

run方法的重构也很简单,先加锁,再加入自己想要的函数,最后解锁。

(2)mythread类的编写,我还是很快就学会了,但问题是如何将test.txt让多线程写入。

一开始,我是这么写的:

for i in range(threadnum):

    threadtemp = myThread(content)

    threadtemp.start()

    threads.append(threadtemp)

发现每个线程都重复将test.txt里的内容都写了一次,也是相当于重复写了4次。这里就是和多进程用法不同的地方了。

【说明】:

多进程,由于不共享资源,因此每个进程都能读取到不同的content内容;多线程,线程之间相互共享,如果要它实现并发的功能,必须给每个线程指定要写的内容。因此最后示例代码中我就通过 content[i * eline:(i + 1) * eline]给每个线程指定了不同的写入内容。

(3)在主函数中,需要把各线程进行start,最后就是等各子线程结束后,主线程再往下执行。

从最后代码行上来看,个人觉得多线程其实是麻烦点的。另外,还有个麻烦的地方是:多线程在调用时是随机调用的,什么意思?就是thread1结束后,第二个运行的是thread9,而不是thread2。那么问题来了,既然大神建议我们用多进程,而且多进程写起来简单,那是不是所有场景都使用多进程呢?

3、多线程和多进程的使用场景:

多线程使用场景:IO操作密集的场景,比如爬虫,web访问等,需要频繁从网络、硬盘、内存等读写数据。这种情况 下,因为单线程下的IO操作会有IO等待,造成不必要的时间浪费,因此采用多线程就能在线程A等待时,开启线程B的操作。

多进程使用场景:CPU计算密集的场景,比如科学计算、循环处理等。这些场景因为计算工作量大,可能会出现单线程超时释放GIL,从而 引发其他多个线程的抢夺,反而效果不好。

那为什么大神们说最好用多进程呢?应该是为了充分利用多核CPU,不然我们的PC机都要买多核CPU呢?

再回到本示例代码,从结果上来看,是多线程的效率更快些,也说明硬盘读写的场景更建议用多线程;但是多线程的结果,即new2.txt里是乱序的,哎。不过我觉得应该有办法解决的,但本人下次再学习。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

推荐阅读:
  1. 多进程与多线程的选择
  2. Python中多线程与多进程对比的示例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python 多线程

上一篇:使用Java无界队列的线程池会怎么样

下一篇:JS的script标签属性有哪些

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》