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. binlog2sql实现MySQL误操作的恢复

    对于MySQL数据库中的误操作删除数据的恢复问题,可以使用基于MySQL中binlog做到类似于闪回或者生成反向操作的SQL语句来实现,是MySQL中一个非常实用的功能.原理不难理解,基于MySQL的 ...

  2. ES6 Promise 用法转载

    Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.catch等同样很眼熟的方法. 那就new一个 var p = new Promise( ...

  3. GitLab管理之 - Gitlab 用户管理

    1. 移除用户 (1) 使用管理员登陆Gitlab服务器 (2) 点击管理区域 (3) 点击Users. (4)点击[Block User] 2. 添加用户(1)用root 管理员登陆.(2)点击[管 ...

  4. linux查看硬件详细信息dmidecode

    [root@zabbix_server src]# dmidecode|more # dmidecode 2.12 SMBIOS 2.7 present. structures occupying b ...

  5. pandas,pd.ExcelWriter保存结果到已存在的excel文件中

    背景:pandas支持将DataFrame数据直接保存到excel中   保存的case如下: import pandas as pd with pd.ExcelWriter('a.xls') as ...

  6. mysql学习5:数据库设计

    mysql学习5:数据库设计 本文转载:https://blog.51cto.com/9291927/2087925:原创为天山老妖S 一.数据库设计简介 按照规范设计,将数据库的设计过程分为六个阶段 ...

  7. gridview 选中某行后 某行的按钮显示,无选中则隐藏

    如后面的加号,选中行时出现,未被选中的隐藏 解决: 在按钮中的visibility属性中绑定该item是否选中,再用转换器转换 <Button Name="btnA" Cli ...

  8. Pyton:类变量,实例变量,类对象,实例对象

    https://www.cnblogs.com/crazyrunning/p/6945183.html

  9. 推荐几个可以从google play(谷歌应用商店)直接下载原版APP的网站

    http://apk-dl.com/ https://apkpure.com/ http://apk-downloaders.com

  10. error: command 'gcc' failed with exit status 1

    MacOS下想安装MySQL-Python,执行语句: sudo pip install MySQL-Python 遇到了如下错误信息: /Users/kaitlyn/anaconda3/envs/e ...