Python多线程threading和multiprocessing模块实例解析


Posted in Python onJanuary 29, 2018

本文研究的主要是Python多线程threading和multiprocessing模块的相关内容,具体介绍如下。

线程是一个进程的实体,是由表示程序运行状态的寄存器(如程序计数器、栈指针)以及堆栈组成,它是比进程更小的单位。
线程是程序中的一个执行流。一个执行流是由CPU运行程序代码并操作程序的数据所形成的。因此,线程被认为是以CPU为主体的行为。

线程不包含进程地址空间中的代码和数据,线程是计算过程在某一时刻的状态。所以,系统在产生一个线程或各个线程之间切换时,负担要比进程小得多。

线程是一个用户级的实体,线程结构驻留在用户空间中,能够被普通的用户级函数直接访问。

一个线程本身不是程序,它必须运行于一个程序(进程)之中。因此,线程可以定义为一个程序中的单个执行流。

多线程是指一个程序中包含多个执行流,多线程是实现并发的一种有效手段。一个进程在其执行过程中,可以产生多个线程,形成多个执行流。每个执行流即每个线程也有它自身的产生、存在和消亡的过程。

多线程程序设计的含义就是可以将程序任务分成几个并行的子任务。

线程的状态图:

Python多线程threading和multiprocessing模块实例解析

Python中常使用的线程模块

  • thread(低版本使用的),threading
  • Queue
  • multiprocessing

threading

thread模块是Python低版本中使用的,高版本中被threading代替了。threading模块提供了更方便的API来操作线程。

threading.Thread

Thread是threading模块中最重要的类之一,可以使用它来创建线程。创建新的线程有两种方法:

  • 方法一:直接创建threading.Thread类的对象,初始化时将可调用对象作为参数传入。
  • 方法二:通过继承Thread类,重写它的run方法。

Thread类的构造方法:

__init__(group=None, target=None, name=None, args=(), kwargs=None, verbose=None)

参数说明:

group:线程组,目前还没有实现,库引用中提示必须是None。
target:要执行的方法;
name:线程名;
args/kwargs:要传入方法的参数。

Thread类拥有的实例方法:

isAlive():返回线程是否在运行。正在运行指的是启动后,终止前。

getName(name)/setName(name):获取/设置线程名。

isDaemon(bool)/setDaemon(bool):获取/设置是否为守护线程。初始值从创建该线程的线程继承而来,当没有非守护线程仍在运行时,程序将终止。

start():启动线程。

join([timeout]):阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的等待时间timeout(可选参数)。即当前的线程要等调用join()这个方法的线程执行完,或者是达到规定的时间。

直接创建threading.Thread类的对象

实例:

from threading import Thread
import time
def run(a = None, b = None) :
 print a, b 
 time.sleep(1)

t = Thread(target = run, args = ("this is a", "thread"))
#此时线程是新建状态

print t.getName()#获得线程对象名称
print t.isAlive()#判断线程是否还活着。
t.start()#启动线程
t.join()#等待其他线程运行结束

执行结果:

Thread-1
False
this is a thread

注意:

t = Thread(target = run, args = ("this is a", "thread"))

这句只是创建了一个线程,并未执行这个线程,此时线程处于新建状态。

t.start()#启动线程

启动线程,此时线程扔为运行,只是处于准备状态。

自定义函数run(),使我们自己根据我们需求自己定义的,函数名可以随便取,run函数的参数来源于后面的args元组。

通过继承Thread类

实例:

from threading import Thread
import time

class MyThread(Thread) :
 def __init__(self, a) :
  super(MyThread, self).__init__()
  #调用父类的构造方法
  self.a = a

 def run(self) :
  print "sleep :", self.a
  time.sleep(self.a)

t1 = MyThread(2)
t2 = MyThread(4)
t1.start()
t2.start()
t1.join()
t2.join()

执行结果:

Python多线程threading和multiprocessing模块实例解析

由于创建了两个并发执行的线程t1和t2,并发线程的执行时间不定,谁先执行完的时间也不定,所以执行后打印的结果顺序也是不定的。每一次执行都有可能出现不同的结果。

注意:

继承Thread类的新类MyThread构造函数中必须要调用父类的构造方法,这样才能产生父类的构造函数中的参数,才能产生线程所需要的参数。新的类中如果需要别的参数,直接在其构造方法中加即可。

同时,新类中,在重写父类的run方法时,它默认是不带参数的,如果需要给它提供参数,需要在类的构造函数中指定,因为在线程执行的过程中,run方法时线程自己去调用的,不用我们手动调用,所以没法直接给传递参数,只能在构造方法中设定好参数,然后再run方法中调用。

针对join()函数用法的实例:

# encoding: UTF-8
import threading
import time

def context(tJoin):
  print 'in threadContext.'
  tJoin.start()
  # 将阻塞tContext直到threadJoin终止。
  tJoin.join()
  # tJoin终止后继续执行。
  print 'out threadContext.'

def join():
  print 'in threadJoin.'
  time.sleep(1)
  print 'out threadJoin.'

tJoin = threading.Thread(target=join)
tContext = threading.Thread(target=context, args=(tJoin,))
tContext.start()

执行结果:

in threadContext.
in threadJoin.
out threadJoin.
out threadContext.

解析:

主程序中这句tJoin = threading.Thread(target=join)执行后,只是创建了一个线程对象tJoin,但并未启动该线程。

tContext = threading.Thread(target=context, args=(tJoin,))
tContext.start()

上面这两句执行后,创建了另一个线程对象tContext并启动该线程(打印in threadContext.),同时将tJoin线程对象作为参数传给context函数,在context函数中,启动了tJoin这个线程,同时该线程又调用了join()函数(tJoin.join()),那tContext线程将等待tJoin这线程执行完成后,才能继续tContext线程后面的,所以先执行join()函数,打印输出下面两句:

in threadJoin.
out threadJoin.

tJoin线程执行结束后,继续执行tContext线程,于是打印输出了out threadContext.,于是就看到我们上面看到的输出结果,并且无论执行多少次,结果都是这个顺序。但如果将context()函数中tJoin.join()这句注释掉,再执行该程序,打印输出的结果顺序就不定了,因为此时这两线程就是并发执行的。

multiprocessing.dummy

Python中线程multiprocessing模块与进程使用的同一模块。使用方法也基本相同,唯一不同的是,from multiprocessing import Pool这样导入的Pool表示的是进程池;
from multiprocessing.dummy import Pool这样导入的Pool表示的是线程池。这样就可以实现线程里面的并发了。

线程池实例:

import time
from multiprocessing.dummy import Pool as ThreadPool
#给线程池取一个别名ThreadPool
def run(fn):
 time.sleep(2)
 print fn

if __name__ == '__main__':
 testFL = [1,2,3,4,5]
 pool = ThreadPool(10)#创建10个容量的线程池并发执行
 pool.map(run, testFL)
 pool.close()
 pool.join()

执行结果:

Python多线程threading和multiprocessing模块实例解析

这里的pool.map()函数,跟进程池的map函数用法一样,也跟内建的map函数一样。

总结

以上就是本文关于Python多线程threading和multiprocessing模块实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python uuid模块使用实例
Apr 08 Python
Python实现统计英文单词个数及字符串分割代码
May 28 Python
Python3实现简单可学习的手写体识别(实例讲解)
Oct 21 Python
python实现简易云音乐播放器
Jan 04 Python
Django中针对基于类的视图添加csrf_exempt实例代码
Feb 11 Python
numpy中loadtxt 的用法详解
Aug 03 Python
python多进程使用及线程池的使用方法代码详解
Oct 24 Python
python 比较2张图片的相似度的方法示例
Dec 18 Python
python爬虫实现获取下一页代码
Mar 13 Python
Python 存取npy格式数据实例
Jul 01 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
Mar 02 Python
python绘图subplots函数使用模板的示例代码
Apr 30 Python
Python编程scoketServer实现多线程同步实例代码
Jan 29 #Python
Python模块搜索路径代码详解
Jan 29 #Python
python机器人行走步数问题的解决
Jan 29 #Python
python的socket编程入门
Jan 29 #Python
Python 错误和异常代码详解
Jan 29 #Python
python实现机器人行走效果
Jan 29 #Python
浅谈Python用QQ邮箱发送邮件时授权码的问题
Jan 29 #Python
You might like
php Smarty 字符比较代码
2011/02/27 PHP
基于php权限分配的实现代码
2013/04/28 PHP
PHP常用的小程序代码段
2015/11/14 PHP
juqery 学习之三 选择器 层级 基本
2010/11/25 Javascript
js模拟滚动条(横向竖向)
2013/02/22 Javascript
推荐10 个很棒的 jQuery 特效代码
2015/10/04 Javascript
详解JavaScript逻辑Not运算符
2015/12/04 Javascript
简单谈谈JS数组中的indexOf方法
2016/10/13 Javascript
Javascript 跨域知识详细介绍
2016/10/30 Javascript
bootstrap日期控件问题(双日期、清空等问题解决)
2017/04/19 Javascript
360doc网站不登录就无法复制内容的解决方法
2018/01/27 Javascript
js循环map 获取所有的key和value的实现代码(json)
2018/05/09 Javascript
vue实现吸顶、锚点和滚动高亮按钮效果
2019/10/21 Javascript
微信小程序停止其他视频播放当前视频的实例代码
2019/12/25 Javascript
jQuery 图片查看器插件 Viewer.js用法简单示例
2020/04/04 jQuery
[36:19]2018DOTA2亚洲邀请赛 小组赛 A组加赛 Newbee vs LGD
2018/04/03 DOTA
Python使用MySQLdb for Python操作数据库教程
2014/10/11 Python
初步探究Python程序的执行原理
2015/04/11 Python
Python编程之基于概率论的分类方法:朴素贝叶斯
2017/11/11 Python
Python实现OpenCV的安装与使用示例
2018/03/30 Python
Python3.5运算符操作实例详解
2019/04/25 Python
详解python pandas 分组统计的方法
2019/07/30 Python
关于python导入模块import与常见的模块详解
2019/08/28 Python
Python如何读取文件中图片格式
2020/01/13 Python
Python ORM框架Peewee用法详解
2020/04/29 Python
详解KMP算法以及python如何实现
2020/09/18 Python
"引用"与指针的区别是什么
2016/09/07 面试题
下面关于"联合"的题目的输出是什么
2013/08/06 面试题
在c#中using和new这两个关键字有什么意义
2013/05/19 面试题
工地门卫岗位职责
2013/12/30 职场文书
社会保险接收函
2014/01/12 职场文书
2015年护士节活动策划方案
2015/05/04 职场文书
2015年敬老院工作总结
2015/05/18 职场文书
忠诚教育学习心得体会
2016/01/23 职场文书
Win10玩csgo闪退如何解决?Win10玩csgo闪退的解决方法
2022/07/23 数码科技
canvas 中如何实现物体的框选
2022/08/05 Javascript