• 线程中的setDaemon方法


    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来说,主线程的优先级更高。

  • 相关阅读:
    sqlserver 2005 数据库的差异备份与还原
    sqlserver安装教程
    hibernate左连接查询时在easyUI的dataGrid中有些行取值为空的解决办法
    解释器模式
    命令模式
    责任链模式
    3Sum Closest
    3sum
    代理模式
    外观模式
  • 原文地址:https://www.cnblogs.com/guyexiangyun/p/10563276.html
Copyright © 2020-2023  润新知