Python 线程与进程

Python 线程与进程

Python由于有全锁局的存在(同一时间只能有一个线程执行),并不能利用多核优势。所以,如果程序的多线程进程是CPU密集型的,那多线程并不能带来效率上的提升,相反还可能会因为线程的频繁切换,导致效率下降;如果是IO密集型,多线程进程可以利用IO阻塞等待时的空闲时间执行其他线程,提升效率。

但我们总会有在程序中实现多并发来提升程序运行效率的情形。在这些情形下,可以适当的利用多进程来实现提升效率。

另外,python中,为了解决网络请求密集中,延时等待的问题,我们还可是使用协程来提交效率。

在于IO密集型程序中,多线程应用较多。
但在网络请求密集中,协程比多线程强上很多。
在CPU密集中,还是进程应用更多。
以下是三个例子:

线程:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import threading
import time, datetime


# 为线程定义一个函数
def print_time(thread_name):
    for i in range(3):
        now = datetime.datetime.now()
        print(now, thread_name)
        time.sleep(1)

# 不带线程处理的程序
for i in range(5):
    threadname = "threadName" + str(i)
    print_time(threadname)

#线程处理
# for i in range(5):
#     threadname = "threadName"+str(i)
#     t = threading.Thread(target=print_time(threadname))
#     t.start()

运行发现,不带线程处理的程序和线程处理的程序运行顺序是一样的:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py

2017-11-08 11:55:32.889184 threadName0
2017-11-08 11:55:33.890456 threadName0
2017-11-08 11:55:34.894145 threadName0
2017-11-08 11:55:35.899107 threadName1
2017-11-08 11:55:36.900408 threadName1
2017-11-08 11:55:37.903821 threadName1
2017-11-08 11:55:38.907008 threadName2
2017-11-08 11:55:39.909538 threadName2
2017-11-08 11:55:40.914680 threadName2
2017-11-08 11:55:41.918500 threadName3
2017-11-08 11:55:42.921579 threadName3
2017-11-08 11:55:43.925748 threadName3
2017-11-08 11:55:44.928359 threadName4
2017-11-08 11:55:45.931913 threadName4
2017-11-08 11:55:46.932414 threadName4

Process finished with exit code 0

每个线程执行完需要3秒,依次执行线程,总耗时15秒。

进程

# 进程处理
if __name__ == "__main__":
    for i in range(5):
        threadName = "threadName" + str(i)
        p = multiprocessing.Process(target=print_time, args=(threadName,))
        p.start()

进程处理运行结果如下:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 11:58:44.045175 threadName0
2017-11-08 11:58:44.046196 threadName1
2017-11-08 11:58:44.047036 threadName2
2017-11-08 11:58:44.048071 threadName3
2017-11-08 11:58:44.049010 threadName4
2017-11-08 11:58:45.045841 threadName0
2017-11-08 11:58:45.046783 threadName1
2017-11-08 11:58:45.048291 threadName2
2017-11-08 11:58:45.048476 threadName3
2017-11-08 11:58:45.050095 threadName4
2017-11-08 11:58:46.046989 threadName0
2017-11-08 11:58:46.047063 threadName1
2017-11-08 11:58:46.048629 threadName2
2017-11-08 11:58:46.049239 threadName3
2017-11-08 11:58:46.050937 threadName4

Process finished with exit code 0

每个进程执行完需要3秒,并发执行线程,总耗时3秒。

进程池

# 进程池处理
if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=4)
    for i in range(5):
        threadName = "threadName" + str(i)
        pool.apply_async(print_time, (threadName,))
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

进程池处理结果如下:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 12:01:03.557402 threadName0
2017-11-08 12:01:03.557552 threadName1
2017-11-08 12:01:03.557686 threadName2
2017-11-08 12:01:03.557827 threadName3
2017-11-08 12:01:04.558322 threadName2
2017-11-08 12:01:04.558306 threadName0
2017-11-08 12:01:04.558311 threadName1
2017-11-08 12:01:04.558322 threadName3
2017-11-08 12:01:05.558841 threadName1
2017-11-08 12:01:05.558833 threadName2
2017-11-08 12:01:05.558841 threadName0
2017-11-08 12:01:05.558845 threadName3
2017-11-08 12:01:06.560105 threadName4
2017-11-08 12:01:07.561340 threadName4
2017-11-08 12:01:08.561577 threadName4
Sub-process(es) done.

Process finished with exit code 0

由于设置了进程并发的数量为4,所以,前三秒执行的都是前四个进程的内容(每个进程执行完需要三秒),进程5只能在前四个进程执行完成之后,才开始执行。总耗时6秒。

修改进程并发数量为5:

# 进程池处理
if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=5)
    for i in range(5):
        threadName = "threadName" + str(i)
        pool.apply_async(print_time, (threadName,))
    pool.close()
    pool.join()
    print("Sub-process(es) done.")

运行结果如下:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 12:12:17.210982 threadName0
2017-11-08 12:12:17.211084 threadName1
2017-11-08 12:12:17.211188 threadName2
2017-11-08 12:12:17.211335 threadName3
2017-11-08 12:12:17.211451 threadName4
2017-11-08 12:12:18.211480 threadName0
2017-11-08 12:12:18.211481 threadName2
2017-11-08 12:12:18.211480 threadName1
2017-11-08 12:12:18.211785 threadName3
2017-11-08 12:12:18.211787 threadName4
2017-11-08 12:12:19.211773 threadName2
2017-11-08 12:12:19.211784 threadName0
2017-11-08 12:12:19.212676 threadName1
2017-11-08 12:12:19.212679 threadName4
2017-11-08 12:12:19.212679 threadName3
Sub-process(es) done.

Process finished with exit code 0

修改设置进程并发的数量为5,所以,所有5个进程能够同步执行。每个进程执行完需要三秒,总耗时3秒。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 9,615评论 0 23
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,255评论 25 709
  • 大家好,我是悠贝南山保利绘本馆的真真老师。今天,要为大家推荐的绘本是《花婆婆》—做个爱的使者。 也许你还没有来得及...
    苟苟的脚步_绘本与成长阅读 6,558评论 0 3
  • 都说家有一老,好有一宝,我是幸运的,有两宝,在他们身上让你真真切切体会到什么才是患难与共,相濡以沫。作为女儿有这样...
    马德水阅读 2,600评论 0 1
  • 我们把我们所拥有的最好的东西送给别人,直到我们的爱再也没有东西可以送出为止,但是,我们最好的东西在别人看来,不一定...
    青衫湿旧阅读 3,169评论 21 23