基本知识:

  • 一、什么是多线程Threading
  • 二、添加线程Thread
  • 三、join功能
  • 四、存储进程结果Queue
  • 五、GIL不一定有效率
  • 六、线程锁 Lock

一、什么是多线程Threading

二、添加线程Thread

import threading                   # 导入模块print(threading.active_count())    # 获取激活的线程数
print(threading.enumerate())       # 查看所有线程信息
print(threading.current_thread())  # 查看正在运行的线程def thread_job():print("This is thread of %s",threading.current_thread())if __name__ == '__main__':print("This is thread of %s",threading.current_thread())thread = threading.Thread(target=thread_job,)   # 定义线程:注意target只写函数名,不能带括号thread.start()                                  # 让线程开始工作

结果:

1
[<_MainThread(MainThread, started 4661450176)>]
<_MainThread(MainThread, started 4661450176)>
This is thread of %s <_MainThread(MainThread, started 4661450176)>
This is thread of %s <Thread(Thread-1, started 123145514528768)>

三、join功能

1. 不使用join()的结果:主线程Main thread 和子线程 Thread1 同时进行

import threading
import time                  def thread_job():print("Thread1 start")time.sleep(1)                # 模拟任务消耗时间print("Thread1 finish")if __name__ == '__main__':thread = threading.Thread(target=thread_job,name="Thread1")          thread.start() print("All finish")

预期结果:

Thread1 start
Thread1 finish
All finish

实际结果:

Thread1 start
All finish
Thread1 finish

2. 使用join()的结果:在子线程 Thread1 完成之后再执行主线程Main thread

if __name__ == '__main__':thread = threading.Thread(target=thread_job,name="Thread1")          thread.start() thread.join()print("All finish")

结果:

Thread1 start
Thread1 finish
All finish

3. 如果是多个线程,为了规避不必要的麻烦,推荐1221的V型排布

thread_1.start()
thread_2.start()
thread_2.join()
thread_1.join()
print("All finish")

四、存储进程结果Queue

import threading
import time
from queue import Queue                def thread_job(l,q):          # l:列表,q:队列,功能:计算列表每个元素的平凡,结果保存在队列中for i in range(len(l)):l[i] = l[i]**2q.put(l)                  # 多线程调用的函数不能用return返回值,故用队列保存结果if __name__ == '__main__':q = Queue()data = [[1,2,3],[4,5,6],[7,8,9]]threads = []for i in range(3):        # 定义三个线程t = threading.Thread(target=thread_job,args=(data[i],q))t.start()             # 开启线程threads.append(t)     # 把每个线程加入到线程列表中for thread in threads:    # 将3个线程join到主线程中thread.join()for _ in range(3):print(q.get())        # 使用q.get()按顺序从q中取出结果

结果:

[1, 4, 9]
[16, 25, 36]
[49, 64, 81]

五、GIL不一定有效率

python 多线程有时候并不理想,主要原因是python的设计上有一个必要环节Global Interpreter Lock(GIL)全局锁。使得python还是一次性只能处理一个东西。

尽管Python完全支持多线程编程, 但是解释器的C语言实现部分在完全并行执行时并不是线程安全的。
实际上,解释器被一个全局解释器锁保护着,它确保任何时候都只有一个Python线程执行。
GIL最大的问题就是Python的多线程程序并不能利用多核CPU的优势 (比如一个使用了多个线程的计算密集型程序只会在一个单CPU上面运行)。
在讨论普通的GIL之前,有一点要强调的是GIL只会影响到那些严重依赖CPU的程序(比如计算型的)
如果你的程序大部分只会涉及到I/O,比如网络交互,那么使用多线程就很合适,因为它们大部分时间都在等待。
实际上,你完全可以放心的创建几千个Python线程, 现代操作系统运行这么多线程没有任何压力,没啥可担心的。

import threading
import timedef job():                  # 任务函数for _ in range(10):time.sleep(0.0001)def multiThreading():      # 使用 N 个线程执行任务threads = []for i in range(10):t = threading.Thread(target=job,)t.start()threads.append(t)[t.join() for t in threads]def normal():               # 依次执行任务 N 次for i in range(10):job()if __name__ == '__main__':  # 多线程执行和普通顺序调用消耗时间对比nor_start_time = time.time()normal()print("normal_time:",time.time()-nor_start_time)mul_start_time = time.time()multiThreading()print("multiThreading_time:",time.time()-mul_start_time)

当任务执行10次时普通顺序调用和多线程消耗时间:

normal_time: 0.014399051666259766
multiThreading_time: 0.00513005256652832

按理来说,多线程应该比普通方法速度快10倍,因为建立了10个线程,但是结果并没有。这就是其中的GIL在作怪。

六、线程锁 Lock

1. 不使用 Lock 的情况
在一个线程执行运算修改共享内存的过程中,其他线程也可以访问该共享内存,会造成共享内存数据的混乱。

import threadingdef job1():global Afor i in range(10):A += 1print("Job1:",A)def job2():global Afor i in range(10):A += 10print("Job2:",A)if __name__=="__main__":A = 0t1 = threading.Thread(target=job1)t2 = threading.Thread(target=job2)t1.start()t2.start()t2.join()t1.join()

结果:

Job1: 1
Job1: 2
Job1: 13
Job2: 12
Job1: 14
Job2: 24
Job1: 25
Job2: 35
Job1: 36
Job2: 46
Job1: 47
Job2: 57
Job1: 58
Job2: 68
Job1: 69
Job2: 79
Job1: 80
Job2: 90
Job2: 100
Job2: 110

2. 使用 Lock 的情况
Lock 在不同线程使用同一共享内存时,能够确保线程之间互不影响
方法:在每个线程执行运算修改共享内存之前,执行 lock.acquare() 将共享内存上锁,确保当前线程访问时,共享内存不会被其他线程访问,执行运算完毕后,使用 lock.release() 将锁打开,保证其他线程可以使用该共享内存。

import threadingdef job1():global A,locklock.acquire()       # 上锁for i in range(10):A += 1print("Job1:",A)lock.release()       # 开锁def job2():global A,locklock.acquire()       # 上锁for i in range(10):A += 10print("Job2:",A)lock.release()       # 开锁if __name__=="__main__":A = 0lock = threading.Lock()t1 = threading.Thread(target=job1)t2 = threading.Thread(target=job2)t1.start()t2.start()t2.join()t1.join()

结果:

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

学习视频连接:?莫烦PYTHON

一篇文章学习Python中的多线程相关推荐

  1. 一篇文章学习Python中的多进程

    基本知识: 一.什么是多进程 Multiprocessing 二.添加多进程 Process 三.存储进程输出 Queue 四.效率对比 threading & multiprocessing ...

  2. 草根方式学习java中的多线程

    草根方式学习java中的多线程 下面有具体的代码和截图 源码点这里 多线程即在同一时间,可以做多件事情(说白了,就是齐头并进) 单线程就是按部就班 创建多线程有2种方式,分别是继承线程Thread类, ...

  3. PYTHON 中的多线程

    通常我们构建的应用程序可能需要多个任务在同一个应用程序中同时运行.这就是python中多线程概念发挥作用的地方.这篇文章提供了在 Python 中使用多线程(又名 Python 中的线程)的全面解释. ...

  4. Python基础学习-Python中最常见括号()、[]、{}的区别 2015-08-13 07:54 by xuxiaoxiaoxiaolu, 1138 阅读, 0 评论, 收藏, 编辑 Pytho

    Python基础学习-Python中最常见括号().[].{}的区别 2015-08-13 07:54 by xuxiaoxiaoxiaolu, 1138 阅读, 0 评论, 收藏, 编辑 Pytho ...

  5. 浅谈 Python 中的多线程。

    本文作者:Rocky0249 公众号:Python空间 00.写在之前 大家好,我是 Rocky0429,今天我来写一下 Python 中的多线程.在正式开始之前,我先用比较通俗的语言给大家介绍几个比 ...

  6. Python中的多线程

    Python中的多线程 文章目录 Python中的多线程 一.线程介绍 1.什么是线程 2.为什么要使用多线程 3.多线程的优点 二.线程实现 1.**`普通创建方式`** 2.**`自定义线程`** ...

  7. js打印线程id_浅谈python中的多线程和多进程(二)

    原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文<浅谈python中的多线程和多进程>中我们分享过一个例子,就是分别利用python中的多线程和多进程来解决高 ...

  8. 获得进程id_浅谈python中的多线程和多进程(二)

    原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文<浅谈python中的多线程和多进程>中我们分享过一个例子,就是分别利用python中的多线程和多进程来解决高 ...

  9. python中的多线程求值串行和并行_python多线程和多进程——python并行编程实验

    工作中经常涉及到加速程序的运行,除了代码逻辑的优化,算法的优化之外,还经常使用的一招就是并发编程.至于python的并型编程这一块.说到并行编程,我们不得不谈线程和进程这两个概念: + 进程:对于操作 ...

最新文章

  1. 【 FPGA 】FIR 滤波器的架构
  2. VTK:可视化算法之MarchingCases
  3. Java集合容器系列04-HashMap
  4. 克服SOA实施过程中的障碍
  5. 红包指定分配金额php,php仿微信红包分配算法的实现方法_PHP
  6. oracle移动硬盘盒,oracle-linux下挂载移动硬盘 NTFS类型
  7. su生成面域插件_插件玩的溜,SU不用愁
  8. 排列生成算法--C++
  9. 如何评价NVIDIA RTX 2080 Ti显卡?
  10. 设置jupyter notebook的启动及工作目录方法汇总
  11. 【离散数学·图论】关于哈密顿图的判别条件总结
  12. html5在线显示ofd文件,基于HTML5的OFD文件在线显示的方法以及装置制造方法及图纸...
  13. ARM-Linux 交叉编译工具链安装
  14. python拨号_Python进行ADSL拨号
  15. 游戏音效制作需要哪些要求
  16. “collect2: error: ld returned 1 exit status“解决方法
  17. 力扣(LeetCode)244. 最短单词距离 II(2022.09.01)
  18. 短距离无线通信设备的天线设计
  19. 运行成功但模拟器上没有程序
  20. linux 开机运行命令

热门文章

  1. c/c++整理--c++面向对象(3)
  2. 终极教程,带具体实验现象,1个GPIO控制2个LED显示4种状态,欢迎讨论!
  3. android人脸识别demo_零门槛解决Windows人脸识别应用开发难题
  4. Cs代码写在html页面哪里,当用于在details.cshtml页面上查看时,我用什么代码来查看模型中的项目列表?...
  5. 每日一题(47)—— 置1与清0
  6. kstools工具是什么牌子_2020年平衡车推荐,电动平衡车哪个牌子好?老司机教你如何选购电动平衡车...
  7. python web开发 网络编程 TCP/IP UDP协议
  8. 天池 在线编程 卡牌游戏(01背包)
  9. 剑指Offer - 面试题40. 最小的k个数(排序/大顶堆)
  10. python3 可执行文件_将python3打包成为exe可执行文件(pyinstaller)