当前位置:   article > 正文

python多线程_Python多线程和多进程

3c93759748ee435ebf1c7ee66a537d85.png

前几天处理数据,发现只开一个进程实在是太慢了。于是借此机会刚好把多线程和多进程复习一下。我主要看的是B站的莫烦python两个系列。周大神(周沫凡先生)的讲解比纯看文字容易多了。且像其他文字版的教程,有点太跳跃了。感谢周大神的讲解~以下内容均是我根据他的视频的整理。

Multiprocessing 让你的多核计算机发挥真正潜力 (莫烦 Python 教程)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
f7bc50ed19c87b366bbb2461645b9cbd.png
Threading 学会多线程 (莫烦 Python 教程)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
2cf9cfa015f6aaa6e5ea10dfd5b17e4f.png

一、多线程Multi-Threads

1、线程的基本统计

import 

输出结果为

  1. 5
  2. [<_MainThread(MainThread, started 21440)>, <Thread(Thread-4, started daemon 15276)>, <Heartbeat(Thread-5, started daemon 17844)>, <HistorySavingThread(IPythonHistorySavingThread, started 13528)>, <ParentPollerWindows(Thread-3, started daemon 21116)>]
  3. <_MainThread(MainThread, started 21440)>

表示有5个已经active的threading,一个是mainthread,另外是thread-4、thread-5、thead-3、savingThread;正在运行的是主线程。

2、增加target和传参args

def 

运行结果

This is an added thread, numbet is <Thread(Thread-9, started 13780)>.

3、join功能

(1)没有join的时候,同时出现多个线程的情况

import 

运行结果是

  1. T1 start
  2. All done
  3. T1 finishes

可以看到,没有等到T1全部结束、就提前运行了all done,最后才是T1 finish。其实多线程是同时在进行的线程任务;如果某些时候想等到所有线程都完成之后、再进行其他的语句,那么需要用到join。

(2)通过join强制所有的子线程结束后、再运行主线程

def 

运行结果

  1. T1 start
  2. T1 finishes
  3. All done

(3)多个线程

def 

运行结果:如果没join,那么顺序比较乱:首先是T1开始、T2开始、T2结束、主线程结束、T1结束

  1. T1 start
  2. T2 start
  3. T2 finishes
  4. All done
  5. T1 finishes

如果加上join

def 

运行结果

  1. T1 start
  2. T2 start
  3. T2 finishes
  4. T1 finishes
  5. All done

4、Queue

  • 多线程没有返回值,需要把运算的结果放在队列Queue中;然后对每个线程的结果从队列中取出来queue.get()、放到主线程中继续运算。
import 

运行结果

[[1, 1, 1], [4, 4, 4], [9, 9, 9], [16, 16, 16]]

5、多线程未必更快

  • 多线程存在GIL(global interpret lock)。为了实现多线程功能,程序把线程锁住,然后锁住了之后,只有唯一一个线程运算。Python只能够让线程在同一时间运算一个东西。在不停切换,看起来是多线程的。但实际上不是。
import 

运行结果

  1. 1999998000000
  2. Normal : 0.1705458164215088
  3. 1999998000000
  4. multi_threading : 0.14860320091247559

不用多线程是 0.1705秒;用了多线程仅仅是稍微快了一点。

6、lock锁

  • 第一个线程处理好了,结果传递给第二个线程,那么需要“锁住“第一个线程。同时需要共享的内存shared memory。
  • 如果不加任何lock:
# 不加任何处理,同时运行两个线程

运行结果

  1. Job1 : 1
  2. Job1 : 2
  3. Job1 : 3
  4. Job2 : 13Job1 :
  5. Job2 : 24
  6. Job2 : 34
  7. Job2 : 44
  8. Job2 : 54
  9. Job2 : 64
  10. Job2 : 74
  11. Job2 : 84
  12. Job2 : 94
  13. Job2 : 104
  14. 14
  15. Job1 : 105
  16. Job1 : 106
  17. Job1 : 107
  18. Job1 : 108
  19. Job1 : 109
  20. Job1 : 110

这两个线程会同时运行,且打印还比较乱。如果我想先结束job1,再进行job2,那么使用lock——定义一个全局变量lock,同时在每个job中传入lock。从而两者运行就不会相互影响。

  • 加上lock
def 

运行结果

  1. Job1 : 1
  2. Job1 : 2
  3. Job1 : 3
  4. Job1 : 4
  5. Job1 : 5
  6. Job1 : 6
  7. Job1 : 7
  8. Job1 : 8
  9. Job1 : 9
  10. Job1 : 10
  11. Job2 : 20
  12. Job2 : 30
  13. Job2 : 40
  14. Job2 : 50
  15. Job2 : 60
  16. Job2 : 70
  17. Job2 : 80
  18. Job2 : 90
  19. Job2 : 100
  20. Job2 : 110

二、多进程Multi-Processing

  • 注意:涉及到windows+multiprocessing,anaconda系列已经没法运行了(陷入死循环)。这里我选择在jupyter中写好了程序,然后放到.py文件中,最后通过cmd运行。
  • multiprocessing和multithread的用法基本一致。

1、简单介绍

import 

写好了,放到叫做code1.py的文件中,然后通过“win+R”进入cmd,通过cd 路径,进入存方code1.py的文件夹。然后通过python code1.py运行

39fb2963f2c96ea12433db90f56185e9.png

如果不能够运行,那么说明是环境变量没有配置好。配置环境变量如下,把python.exe的绝对路径添加到环境变量路径中。

073cfea219153ef1e8f897dda39a9077.png

46e4623d9ef6bad9c0f39c2189dd465b.png

2、效率对比:多线程、多进程、普通程序

import 

同样,存在code.py中,然后通过cmd运行。

ac20141594ef09c85b83bfa78da47335.png

normal时间最长,多线程、多进程存在优势。

3、pool进程池

  • 把所有要运行的东西放到池子中,python自己解决进程分配。
import 

4、apply_async

import 

在cmd中运行,结果

0556eccc5c6c69bacc211101e65dda53.png

5、共享内存:shared memory

  • 传统上,共享一个变量,通过global定义全局变量,放到多线程中,就能够共享变量。
  • 多进程中,即便传入一个全局变量A,分给每一个CPU,但是它们想要交流A行不通(例如核1计算A+1、传给核2计算A×2、传给核3)。这里需要通过共享内存才能够实现。 1、mp.Value(),这个是共享的值,定义了这个值,需要声明它的格式。例如,mp.value('i',1)就是整数,mp.value('d',0.1)就是double型。就能够被每个核读取。 2、mp.Array(),和numpy.array有区别。这个是一维列表,不是多维的。声明数据格式,mp.Array('i', [1,2,3])(多维列表是错的mp.Array('i', [[1],[2],[3]])错错错)。

6、lock-进程锁

  • 如果没有共享内存,那么出现互相争抢value
import 

在cmd运行结果是

9b24a2bb796df98ff52a1e20dc536d29.png
  • 如果通过lock锁住,那么就能够避免争抢value
import 

5507e30df3d59a73c41f50c625d7dca0.png

三、总结

以上是看了周大神的视频的整理。后续我自己也将多线程用到了数据清洗中,效率确实比傻傻地用一个主线程要快多了。

希望对大家有用~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/566417
推荐阅读
相关标签
  

闽ICP备14008679号