setDaemon方法必须在start方法前定义。t1.setDaemon(True),该语句的意思是:将主线程A设置为子线程t1的守护线程。也就是在执行程序时,t1会随着主线程A的退出而退出,不论t1是否执行完毕。

例1:当我们在程序中设置一个子线程并将其设为被守护线程时,那么该子线程会随着主线程的退出而退出,整个程序会在主线程执行结束后终止。

import threading
import time def print_number(num): print("-----> %d" % num, time.ctime())
time.sleep(5)
print("print_number ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,)) if __name__ == '__main__': t1.setDaemon(True) t1.start() print("Main thread ended...")

输出结果如下:

-----> 10 Wed Mar 20 10:54:21 2019
Main thread ended... ***Repl Closed***

可以看到,主线程结束后,子线程t1的最后一句并未被打印出来,因为它随着主线程的退出而退出。

例2:当我们设置了多个子线程时,将其中一个子线程t1设置为被守护线程,那么只有t1会随着主线程的退出而退出,其他子线程不会受到影响,依然会被执行完毕。此时就会出现一种很奇怪的情况,如下所示:

import threading
import time def print_number(num): print("-----> %d" % num, time.ctime())
time.sleep(5)
print("print_number ending......", time.ctime()) # 此处不应该被打印 def print_letter(letter): print("-----> %s" % letter, time.ctime())
time.sleep(10)
print("print_letter ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,))
t2 = threading.Thread(target=print_letter,args=('hello',)) if __name__ == '__main__': t1.setDaemon(True) t1.start()
t2.start() print("Main thread ended...")

在这段代码中,我们设置了两个子线程:t1和t2,并将t1设置为被守护线程。按照上述解释,t1应该在主线程结束时一并推出,所以t1的最后一句“print("print_number ending......", time.ctime())” 不会被运行。但是结果却不是这样:

-----> 10 Wed Mar 20 10:58:00 2019
-----> hello Wed Mar 20 10:58:00 2019
Main thread ended...
print_number ending...... Wed Mar 20 10:58:05 2019 # t1线程的最后一行输出
print_letter ending...... Wed Mar 20 10:58:10 2019 ***Repl Closed***

可以看到,在主线程最后一句输出“Main thread ended...”之后,t1的最后一行代码也被打印了,并不如我们所期待的那样,最后一句不被打印。这是因为什么呢?

此时我们一共存在着3个线程:主线程、子线程t1 和 t2。t1是被守护的子线程,它的执行时间是5秒;t2不是被守护线程,它的执行时间是10秒。由于t2并不被守护,所以在主线程打印最后一句"Main thread ended..."后,t2依然在执行。这是需要注意的是,虽然主线程的代码执行完毕了,但是主线程并未退出。它依然在后台运行并等待t2执行结束。我们所说的守护线程,是随着主线程的退出而一并退出的。但是,如果依然有其他子线程在运行,主线程并不会马上退出,它会等待所有子线程结束后才会推出。所以,我们看到,主线程虽然执行完毕(但在后台并未退出),被守护的t1(时间较短)依然会继续执行后面的代码,因为子线程t2还在运行,所以主线程依然在后台挂起。当子线程t2(时间较长)执行完毕并退出后,主线程才会退出。

代码执行完毕 并不等于 线程的退出。即使主线程没有任何代码需要执行,主线程仍会在后台运行,并等待所有的子线程退出后才会退出。

例3: 如果我们想看到随着主线程退出而子线程退出的情况,那么就可以将t2设置为守护线程。

import threading
import time def print_number(num): print("-----> %d" % num, time.ctime())
time.sleep(5)
print("print_number ending......", time.ctime()) def print_letter(letter): print("-----> %s" % letter, time.ctime())
time.sleep(10)
print("print_letter ending......", time.ctime()) t1 = threading.Thread(target=print_number,args=(10,))
t2 = threading.Thread(target=print_letter,args=('hello',)) if __name__ == '__main__': t2.setDaemon(True) # 将执行时间较长的t2设置为守护线程 t1.start()
t2.start() print("Main thread ended...")

运行结果如下所示:

-----> 10 Wed Mar 20 11:24:59 2019
-----> hello Wed Mar 20 11:24:59 2019
Main thread ended... # 主线程执行完毕,并未退出,等待其他子线程(t1)执行
print_number ending...... Wed Mar 20 11:25:04 2019 # 线程t1执行完毕并退出 ***Repl Closed***

由于t1比t2的执行时间短,所以t1会先执行完毕并推出。而t2为被守护线程,所以它会随着主线程的退出而退出。在t1执行完毕并退出后,主线程不需要再等待其他子线程了,所以主线程就会退出,而t2会随着主线程一并退出,因此t2中的最后一行代码没有被执行。

join方法与setDaemon方法本质上是作用相反的两个方法:

1、join方法:t1.join--->是将t1的优先级提高,阻塞主线程,等待t1执行结束后再执行主线程以及其他子线程。

2、setDaemon方法:t1.setDaemon(True)--->是将t1捆绑到主线程上,它会随着主线程的退出而退出,并不考虑自己的代码是否执行完毕。所以对于t1来说,主线程的优先级更高。

线程中的setDaemon方法的更多相关文章

  1. 模拟做饭系统(java+线程中的join方法)

    (一)项目框架分析 妈妈要去做饭,发现没有酱油,让儿子去买酱油,然后回来做饭. 根据面向对象的思想,有两个对象,妈妈和儿子 主要有两个方法: (一)没有线程控制(即儿子没有买酱油回来妈妈就做好饭了)+ ...

  2. 线程中更新ui方法汇总

    一.为何写作此文   你是不是经常看到很多书籍中说:不能在子线程中操作ui,不然会报错.你是不是也遇到了如下的疑惑(见下面的代码): @Override protected void onCreate ...

  3. 线程中的join方法,与synchronized和wait()和notify()的关系

    什么时候要用join()方法? 1,join方法是Thread类中的方法,主线程执行完start()方法,线程就进入就绪状态,虚拟机最终会执行run方法进入运行状态.此时.主线程跳出start方法往下 ...

  4. 线程中调用service方法出错

    public class PnFileTGIComputeThread implements Runnable { @Resource private AppUsedService appUsedSe ...

  5. 线程中的join方法

    join方法的作用是同步线程. 1.不使用join方法:当设置多个线程时,在一般情况下(无守护线程,setDeamon=False),多个线程同时启动,主线程执行完,会等待其他子线程执行完,程序才会退 ...

  6. 线程中t.setdaemon(), t.jion(), t.start的使用

    import threading import time def f0(): pass def f1(a1,a2): time.sleep(10) f0() ") t1 = threadin ...

  7. 老问题:Android子线程中更新UI的3种方法

    在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 方法一:用Handler 1.主线程中定义Handler: Handle ...

  8. Android子线程中更新UI的4种方法

    方法一:用Handler 1.主线程中定义Handler: Handler mHandler = new Handler() { @Override public void handleMessage ...

  9. java中创建线程的3种方法

    1.继承Thread类优点:可以直接使用Thread类中的方法,代码比较简单.缺点:继承Thread类之后不能继承其他类. 2.实现Runable接口优点:实现接口,比影响继承其他类或实现接口.缺点: ...

随机推荐

  1. Python 学习笔记01篇

    编程基础很零碎 看了路飞学城的讲解视频,整体课程列表排列很清晰,每个视频都在十几分钟到二十几分钟之间,适合零碎化的的学习 第一章和第二章的前半部分可以较轻松地入门

  2. rest_framework_extensions实现缓存

    1.安装包 pip install drf-extensions pip install django-redis pip install django-redis-cache 2.配置redis # ...

  3. Day09 -超级经典面试题:Ruby的a ||= b(or-equals)是什么意思呢?

    前情提要: 写了这一系列下来,发现Ruby有许多特别的方法.前几天提到String字串,并且接续着在第八天我们了解串接(concatenate)与插入interpolation#{}方法(就连加号+也 ...

  4. 深入理解C++11【5】

    [深入理解C++11[5]] 1.原子操作与C++11原子类型 C++98 中的原子操作.mutex.pthread: #include<pthread.h> #include <i ...

  5. Linux ansible 常用模块二

    fetch 将远程机器上的文件拉取到本地,以ip或者主机名生成目录,并保留原来的目录结构 dest  #目标地址src   #源地址ansible web -m fetch -a "dest ...

  6. 浏览器登录EBS系统遇到问题总结

    1.可以登录EBS系统,但是职责位置为空白 这是兼容性视图问题,将ERP域名加入兼容性视图列表即可. 加入即可: 2.可以登录EBS系统,但是职责位置显示 “undefined” 这也是兼容性视图问题 ...

  7. pandas中的时间序列基础

    重要的数据形式时间序列 datetime以毫秒形式存储日期和时间 now = datetime.now() now datetime.datetime(2018, 12, 18, 14, 18, 27 ...

  8. Auzone AT60 TPMS Tool Update & Authorization Service: FREE

    This is a tutorial with step-of-step explanation of Auzone AT60 TPMS Tool Update & Authorization ...

  9. java实现将包含多个<REC>的文件拆成若干只包含一个<REC>的文件

    遍历文件夹里的文件,将包含多个<REC>的文件拆成若干只包含一个<REC>的文件 package com.prepub; import java.io.BufferedRead ...

  10. python中reshape重组数据方式

    方法numpy.reshape()是怎么进行数据重新定义shape?先生成一个随机数组 reshape成5行3列,可以看到是把(5,3)中第一行的剩余两列数据作为第二行的前两列,以此类推 reshap ...