一、前言

  一个程序至少有一个主线程,主线程启动子线程后,它们之间并没有隶属关系。主线程和子线程执行是并行的,相互独立。主线程执行完毕后默认不等子线程执行结束就接着往下走了,如果有其他程序就会运行另外的程序,如果没有就等待子线程执行完成后结束程序。

  结果:

  

二、join 等待子线程完成

  如果在线程实例后加上join默认主线程是阻塞的,主线程会等待该子线程运行完成后在结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# -*- coding: UTF-8 -*-
 
import threading
import time
import random
 
 
class MyThread(threading.Thread):
 
    def __init__(self, n):
        super(MyThread, self).__init__()
        self.n = n
 
    def run(self):
        print('task %s is operating' % self.n)
        t_time = random.randint(18)
        time.sleep(t_time)
        print(self.getName(), 'finished''I sleep %d seconds' % t_time)
 
 
if __name__ == '__main__':
 
    start_time = time.time()
    for in range(5):
        = MyThread(i)
        t.start()
        t.join()    # 添加join,阻塞主线程
    print('main thread finished.')
    print('cost: %s' % (time.time() - start_time))
 
# 注
# 如果对每个线程都加join,那么并发就没有了,实际上线程都是串行的
# 前一个线程执行完了,才会执行下一个线程
# 主线程最后运行完毕

  结果:

  2.1 计算并发运行时间

  如果不想计算出总的运行时间,而是所有线程的并发运行时间呢?就像上例中的那样,最长运行时间是8秒,那么所有线程都能在8秒内全部运行完毕。

  把t.join()单独移到for循环外面是不行的,因为这样并发运行总会在最后一个线程出阻塞。如下:  

  结果:

  正确的方法,定义一个空列表,获取所以的线程实例,for 循环阻塞所有的线程实例 

  结果,事实上也符合我们刚才的推论,运行时间最长的线程所消耗的时间,就是总的并发时间 

  总结:主线程创建一个子线程后,如果子线程调用join()方法,主线程会在调用的地方等待,直到该子线程运行完成才会接着往下执行。

三、守护线程setDaemon

  setDaemon()方法:在主线程中创建子线程,该子线程调用setDaemon方法后成为主线程的守护线程。这种情况下如果主线程执行结束,那么不管子线程是否完成,一并和主线程退出。这里基本和join()方法相反。此外,还有个要特别注意的:必须在start() 方法调用之前设置,如果不设置为守护线程,程序会被无限挂起。  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# -*- coding: UTF-8 -*-
 
import threading
import time
import random
 
 
class MyThread(threading.Thread):
 
    def __init__(self, n):
        super(MyThread, self).__init__()
        self.n = n
 
    def run(self):
        print('task %s is operating' % self.n)
        t_time = random.randint(18)
        time.sleep(t_time)
        print(self.getName(), 'finished''I sleep %d seconds' % t_time)
 
 
if __name__ == '__main__':
 
    start_time = time.time()
    for in range(5):
        = MyThread(i)
        t.setDaemon(True)
        t.start()
    print('main thread finished.', threading.current_thread(), threading.active_count())
    print('cost: %s' % (time.time() - start_time))

  注:threading.current_thread()查看当前运行的线程

    threading.active_count() 查看活跃线程数

    线程数 =  主线程 + 子线程数

  结果: 

1
2
3
4
5
6
7
8
9
10
11
task 0 is operating
task 1 is operating
task 2 is operating
task 3 is operating
task 4 is operating
main thread finished. <_MainThread(MainThread, started 8656)> 6
cost: 0.0009999275207519531
 
Process finished with exit code 0
 
# 很显然把子线程设置为主线程的守护线程后,主线程一旦结束,程序就执行退出运行,不会再等待子线程运行。

  注:如果程序中有其他非守护线程时,还是会等待非守护线程运行完毕,程序才会结束。

最新文章

  1. btn-default
  2. [C]基本数据类型:整型(int)用法详解
  3. Android分享中,如何过滤指定的应用,并且对不同的分享方式发送不同的内容?
  4. poj2104 线段树 划分树
  5. Eclipse中Build Workspace 优化
  6. html --- canvas --- javascript --- 在线画板
  7. html,css所遇问题(一)
  8. 【Grunt】
  9. ubuntu14.04源代码安装postgresql 9.1
  10. twisted学习笔记4 部署Twisted 应用程序
  11. 从字符串获得MAC地址的方法
  12. 重要:关于PPT转图片需要注意的问题
  13. spring bean中子元素lookup-method和replaced-method
  14. 面向服务的体系架构 SOA(三) --- Zookeeper API、zkClient API的使用
  15. 在Android中使用FFmpeg(android studio环境)
  16. vue框架之自定义组件中使用v-model
  17. php的ajax简单实例
  18. resize定义元素尺寸大小
  19. python 异常知识点
  20. hdu 2176 取石子游戏

热门文章

  1. kafka入门(2)- 环境部署
  2. 让PHPCms内容页支持JavaScript的修改方法
  3. 个人集群部署hadoop 2.7 + hive 2.1
  4. php empty()与isset()
  5. 【译】第五篇 Integration Services:增量加载-Deleting Rows
  6. iframe测试
  7. csv导入mysql提示错误[Error Code] 1290 - The MySQL server is running with the --secure-file-priv option 解决方法【转】
  8. docker stack 部署 seafile(http)
  9. Linux sudo 配置
  10. 链家2018春招C/C++开发实习生在线考试编程题