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. TCP连接笔记

    每个socket套接字都有一个引用计数. 调用close时只是将相应的引用计数减1. 只有当引用计数为0时才会真正的清理套接字资源,也就是发送FIN. 若只是想在某个TCP连接上发送一个FIN可以改用 ...

  2. 同机器与不同机器redis集群

    此文为另外一位大神原创由于没有找到分享功能  粘贴复制到此  原地址为https://blog.csdn.net/u012042021/article/details/72818759 一.同机器下的 ...

  3. CSS 背景图像 填充部分元素示例

    填充部分元素示例 为某个元素设置CSS规则background-image 属性,则可以做到部分元素有背景颜色. 下面的示例演示如何如何给段落元素加背景. <!DOCTYPE html> ...

  4. C# File API

    [C# File API] 1.System.IO.File Provides static methods for the creation, copying, deletion, moving, ...

  5. Linux下使用ps命令查看某个进程文件的启动位置

    ps -ef|grep shutdown ls -al /proc/4170

  6. git命令行获取某分支代码

    参考https://www.cnblogs.com/nylcy/p/6569284.html git clone -b branch1 http://xxx.xx.xxx... git clone - ...

  7. springboot+dubbo修改扫描路径引起端口占用的问题

    因为在多模块项目中引入了spring security,消费方(控制层)的工程有两个包,一个controller,一个config.引入之前消费方工程的application.properties中s ...

  8. QT Designer基础——登录界面设计基础版2

    认识QT Designer提供的可选控件:以下八个大类 Layouts:布局相关 Spacers:留空 Buttons:可点击的按钮类 Item Views和 Item Widgets:高级控件,例如 ...

  9. 独立安装CentOS7.4全记录

    大学用了四年的笔记本快用废了,闲来想着用来装个centos,当个服务器也行,于是装上了CentOS6.9系统,由于最小化安装,而且在安装时没有安装wpa_supplicant包,笔记本本身网卡接口又坏 ...

  10. scrapy 的log功能

    只需要在配置文件 setting.py文件中加入LOG_FILE = "mySpider.log"LOG_LEVEL = "INFO" Scrapy提供5层lo ...