详解python中的线程


Posted in Python onFebruary 10, 2018

Python中创建线程有两种方式:函数或者用类来创建线程对象。

函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。

类:创建threading.Thread的子类来包装一个线程对象。

1.线程的创建

1.1 通过thread类直接创建   

import threading
  import time
  def foo(n):
    time.sleep(n)
    print("foo func:",n)
  def bar(n):
    time.sleep(n)
    print("bar func:",n)
  s1=time.time()
  #创建一个线程实例t1,foo为这个线程要运行的函数
  t1=threading.Thread(target=foo,args=(3,))
  t1.start()  #启动线程t1
  #创建一个线程实例t2,bar为这个线程要运行的函数
  t2=threading.Thread(target=bar,args=(5,))
  t2.start()  #启动线程t2
  print("ending")
  s2=time.time()
  print("cost time:",s2-s1)

在这段程序里,一个函数会先休眠几秒钟,然后再打印一句话,第二个函数也是先休眠几秒钟,然后打印一句话。

接着程序会实例化两个线程,并调用两个函数来执行,最后会打印程序问总共执行了多少时间

程序运行结果如下:

ending
cost time: 0.002000093460083008
foo func: 3
bar func: 5

程序会先运行父线程,打印"ending",然后打印程序执行父线程的时间,最后才会运行子线程

1.2 通过thread类来继承式创建

import threading
  import time
  # 定义MyThread类,其继承自threading.Thread这个父类
  class MyThread(threading.Thread): 
    def __init__(self):
      threading.Thread.__init__(self)
    def run(self):
      print("ok")
      time.sleep(2)
      print("end t1")
  # 对类进行实例化
  t1=MyThread()  
  # 启动线程
  t1.start()
  print("ending")

2. Thread类的一些常用方法

2.1 join():在子线程完成之前,主线程将一直被阻塞****

线程的join方法必须在子线程的start方法之后定义
在第一个例子中加入两行代码,如下:   

import threading
  import time
  def foo(n):
    time.sleep(n)
    print("foo func:",n)
  def bar(n):
    time.sleep(n)
    print("bar func:",n)
  s1=time.time()
  t1=threading.Thread(target=foo,args=(3,))
  t1.start()
  t2=threading.Thread(target=bar,args=(5,))
  t2.start()
  t1.join()    # 阻塞t1线程
  t2.join()    # 阻塞t2线程
  print("ending")
  s2=time.time()
  print("cost time:",s2-s1)

再次执行程序,运行结果如下:

foo func: 3
bar func: 5
ending
cost time: 5.002285957336426

程序运行到子线程t1中的foo方法时会睡眠3秒钟,与此同时,子线程t2也在睡眠

等到子线程t1睡眠完成后,开始打印foo函数中的print语句,然后子线程t1执行完成

2秒钟之后,子线程t2睡眠完成,开始打印bar函数中的print语句,然后子线程t2也执行完成。

而在这之前,主线程一直处于阻塞状态。等到子线程执行完成之后主线程才会执行

2.2 setDeamon(True)

setDaemon方法作用是将进程声明为守护线程,必须在`start()`方法调用之前,
如果不设置为守护线程,程序会被无限挂起

在程序执行过程中,执行一个主线程,主线程又创建一个子线程时,主线程和子线程会分别运行。

当主线程运行完成时,会检验子线程是否执行完成,如果子线程执行完成,则主线程会等待子线程完成后再退出。

但是有的时候只要主线程执行完成之后,不管子线程是否执行完成,都和主线程一起退出,这个就需要调用setDeamon方法了。

拿第一个例子来说吧,现在我想让子线程t1和t2随同主线程关闭,代码如下:

import threading
  import time
  def foo(n):
    print("foo start")
    time.sleep(n)
    print("foo end...")
  def bar(n):
    print("bar start")
    time.sleep(n)
    print("bar end...")
  s1 = time.time()
  t1 = threading.Thread(target=foo, args=(3,))
  t1.setDaemon(True)
  t1.start()
  t2 = threading.Thread(target=bar, args=(5,))
  t2.setDaemon(True)
  t2.start()
  print("ending")
  s2 = time.time()
  print("cost time:", s2 - s1)

程序运行结果如下 :

foo start
bar start
ending
cost time: 0.003000020980834961

可以看到,把t1和t2都声明为守护线程后,程序自上而下执行,先执行子线程t1中的foo方法,打印foo函数中的第一条打印语句,然后子线程t1进入到睡眠状态。

然后子线程t2执行,打印bar函数中的第一条print语句,然后子线程t2进入睡眠状态,程序切换到主线程运行

主线程打印完"ending"语句,发现子线程t1和t2已经被设置为守护线程,所以主线程不需要再等待两个子线程执行完成,而是立即结束,打印整个程序的执行时间。

整个程序就跟随主线程一起关闭了。

2.3 子线程的一些其他方法

isAlive()      #判断一个线程是否是活动线程
getName()      #返回线程的名字
setName()      #设置线程的名字
  import threading
  import time
  def foo(n):
    time.sleep(n)
    print("foo func:", n)
  def bar(n):
    time.sleep(n)
    print("bar func:", n)
  s1 = time.time()
  t1 = threading.Thread(target=foo, args=(3,))
  t1.setDaemon(True)
  print("线程还未启动时,判断t1是否是活动的线程:", t1.isAlive()) # 线程还未启动,所以是False
  t1.start() # 启动线程
  print("线程已启动时,判断t1是否是活动的线程:", t1.isAlive()) # 线程已启动,所以是True
  print("修改前的线程名为:",t1.getName()) # 获取线程名
  t1.setName("t1")    #设置线程名
  print("修改后的线程名为:",t1.getName()) # 获取线程名
  t1.join()
  print("线程执行完成时,判断t1是不否是活动的线程:", t1.isAlive()) # 线程已执行完成,所以是False
  # print(threading.activeCount())
  print("ending")
  s2 = time.time()
  print("cost time:", s2 - s1)

程序执行结果:

线程还未启动时,判断t1是否是活动的线程: False
线程已启动时,判断t1是否是活动的线程: True
修改前的线程名为: Thread-1
修改后的线程名为: t1
foo func: 3
线程执行完成时,判断t1是不否是活动的线程: False
ending
cost time: 3.001171588897705

3.threading模块提供的一些方法

threading.currentThread()  #返回当前的线程变量
threading.enumerate()    #返回一个包含正在运行的线程的列表,不包括启动前和终止后的线程
threading.activeCount()   #返回正在运行的线程数量,等同于len(threading.enumerate())
  import threading
  import time
  def foo(n):
    time.sleep(n)
    print("foo func:", n)
  def bar(n):
    time.sleep(n)
    print("bar func:", n)
  s1 = time.time()
  t1 = threading.Thread(target=foo, args=(3,))
  t1.setDaemon(True)
  t1.start()
  t2 = threading.Thread(target=bar, args=(5,))
  t2.setDaemon(True)
  t2.start()
  print("程序中正在运行的线程数量:",threading.activeCount())
  print("程序中当前的线程变量:",threading.currentThread())
  print("当前正在运行的线程的列表:",threading.enumerate())
  print("ending")
  s2 = time.time()
  print("cost time:", s2 - s1)

程序执行结果:

程序中正在运行的线程数量: 3
程序中当前的线程变量: <_MainThread(MainThread, started 7064)>
当前正在运行的线程的列表: [<_MainThread(MainThread, started 7064)>, <Thread(Thread-1, started daemon 6384)>, <Thread(Thread-2, started daemon 2640)>]
ending
cost time: 0.002000093460083008

总结

以上所述是小编给大家介绍的详解python中的线程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
详解Python中的多线程编程
Apr 09 Python
在Gnumeric下使用Python脚本操作表格的教程
Apr 14 Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 Python
python实现决策树
Dec 21 Python
python排序函数sort()与sorted()的区别
Sep 18 Python
python安装numpy和pandas的方法步骤
May 27 Python
对Django 中request.get和request.post的区别详解
Aug 12 Python
python实现画图工具
Aug 27 Python
详解Anaconda安装tensorflow报错问题解决方法
Nov 01 Python
python 检测图片是否有马赛克
Dec 01 Python
学会迭代器设计模式,帮你大幅提升python性能
Jan 03 Python
Pandas数据分析的一些常用小技巧
Feb 07 Python
Odoo中如何生成唯一不重复的序列号详解
Feb 10 #Python
python TCP Socket的粘包和分包的处理详解
Feb 09 #Python
python实现Adapter模式实例代码
Feb 09 #Python
python实现Decorator模式实例代码
Feb 09 #Python
Python多线程扫描端口代码示例
Feb 09 #Python
Python编程实现从字典中提取子集的方法分析
Feb 09 #Python
python tensorflow学习之识别单张图片的实现的示例
Feb 09 #Python
You might like
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
JS Loading功能的简单实现
2013/11/29 Javascript
javascript日期格式化示例分享
2014/03/05 Javascript
JavaScript Array对象扩展indexOf()方法
2014/05/09 Javascript
javascript动态创建表格及添加数据实例详解
2015/05/13 Javascript
jQuery带进度条全屏图片轮播特效代码分享
2020/06/28 Javascript
详解JavaScript实现设计模式中的适配器模式的方法
2016/05/18 Javascript
jquery获取所有选中的checkbox实现代码
2016/05/26 Javascript
AngularJS equal比较对象实例详解
2016/09/14 Javascript
详解js的六大数据类型
2016/12/27 Javascript
详解用函数式编程对JavaScript进行断舍离
2017/09/18 Javascript
vue-router+nginx 非根路径配置方法
2018/06/30 Javascript
解决Vue-cli npm run build生产环境打包,本地不能打开的问题
2018/09/20 Javascript
详解vue路由篇(动态路由、路由嵌套)
2019/01/27 Javascript
Angular CLI 使用教程指南参考小结
2019/04/10 Javascript
layui多图上传实现删除功能的例子
2019/09/23 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
关于javascript中的promise的用法和注意事项(推荐)
2021/01/15 Javascript
[03:18]DOTA2放量测试专访820:希望玩家加入国服大家庭
2013/08/25 DOTA
Windows中使用wxPython和py2exe开发Python的GUI程序的实例教程
2016/07/11 Python
Python实现获取照片拍摄日期并重命名的方法
2017/09/30 Python
Python判断字符串是否为字母或者数字(浮点数)的多种方法
2018/08/03 Python
python 获取utc时间转化为本地时间的方法
2018/12/31 Python
python使用pymongo操作mongo的完整步骤
2019/04/13 Python
提升Python程序性能的7个习惯
2019/04/14 Python
详解CSS3 用border写 空心三角箭头 (两种写法)
2017/09/29 HTML / CSS
详解css3 flex弹性盒自动铺满写法
2020/09/17 HTML / CSS
AmazeUI中各种的导航式菜单与解决方法
2020/08/19 HTML / CSS
夏威夷航空官网:Hawaiian Airlines
2016/09/11 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
长青弘远的面试题
2012/06/09 面试题
综合素质的自我鉴定
2013/10/07 职场文书
幼儿教师2014年度工作总结
2014/12/16 职场文书
2019年健身俱乐部的创业计划书
2019/08/26 职场文书
班干部竞选演讲稿(精选5篇)
2019/09/24 职场文书
Redis中缓存穿透/击穿/雪崩问题和解决方法
2021/12/04 Redis