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 

输出结果为

5
[<_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)>]
<_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 

运行结果是

T1 start

All done 

T1 finishes

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

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

def 

运行结果

T1 start

T1 finishes

All done 

(3)多个线程

def 

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

T1 start

T2 start

T2 finishes

All done 

T1 finishes

如果加上join

def 

运行结果

T1 start

T2 start

T2 finishes

T1 finishes

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 

运行结果

1999998000000
Normal :  0.1705458164215088
1999998000000
multi_threading :  0.14860320091247559

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

6、lock锁

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

运行结果

Job1 :  1
Job1 :  2
Job1 :  3
Job2 :  13Job1 : 
Job2 :  24
Job2 :  34
Job2 :  44
Job2 :  54
Job2 :  64
Job2 :  74
Job2 :  84
Job2 :  94
Job2 :  104
 14
Job1 :  105
Job1 :  106
Job1 :  107
Job1 :  108
Job1 :  109
Job1 :  110

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

  • 加上lock
def 

运行结果

Job1 :  1
Job1 :  2
Job1 :  3
Job1 :  4
Job1 :  5
Job1 :  6
Job1 :  7
Job1 :  8
Job1 :  9
Job1 :  10
Job2 :  20
Job2 :  30
Job2 :  40
Job2 :  50
Job2 :  60
Job2 :  70
Job2 :  80
Job2 :  90
Job2 :  100
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

三、总结

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

希望对大家有用~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值