【问题标题】:Daemon threads in Jupyter Notebook don't stopJupyter Notebook 中的守护线程不会停止
【发布时间】:2023-08-06 04:44:01
【问题描述】:

我正在为我的多线程课程编写教程。我在下面有这个简单的代码,它初始化了 3 个线程。线程 1,2,3。

线程 1:等待 4 秒的简单计时器

线程 2:等待 2 秒的简单计时器

线程 3:等待 6 秒的简单计时器,但它是守护进程。

主程序在第三个线程结束之前完成。因为第三个线程是守护进程,我认为它会被杀死。因此,我想知道我的代码或 jupyter-notebook 有什么问题。这是我的代码。

import threading
import logging
import time

def threadLauncher1(name, delay):
    logging.info("Thread %s \t : Starting" %name)
    time.sleep(delay)
    logging.info("Thread %s \t : Finishing" %name)


class threadLauncher2(threading.Thread):
    def __init__(self, name, delay):
        super().__init__()
        self.name = name
        self.delay = delay

    def run(self):
        logging.info("Thread %s \t : Starting" % self.name)
        time.sleep(self.delay)
        logging.info("Thread %s \t : Finishing" % self.name)


if __name__ == "__main__":

    format = "%(asctime)s: %(message)s"
    logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")

    threadLauncherFunction1 = threading.Thread(target=threadLauncher1, args=("Timer 1", 4,))
    threadLauncherFunction1.start()

    threadLauncherFunction2 = threadLauncher2("Timer 2", 2)
    threadLauncherFunction2.start()

    threadLauncherFunction3 = threadLauncher2("Timer 3", 6)
    threadLauncherFunction3.setDaemon(True)
    threadLauncherFunction3.start()

    logging.info("Daemon setting is %s on %s" % (str(threadLauncherFunction3.isDaemon()), threadLauncherFunction3.name))

    threadLauncherFunction1.join()
    logging.info("Waited until Timer 1 had finished")
    logging.info("Timer3 should not be able to finish, since it is a daemon Thread")

我尝试用更明确的函数替换第三个线程。

class threadLauncher3(threading.Thread):
    def __init__(self, name, delay):
        super().__init__()
        self.name = name
        self.delay = delay

    def run(self):
        while True:
            logging.info('Thread %s running.' %self.name)
            time.sleep(self.delay)

正如之前的结果所预期的那样,输出是:

13:19:37: Thread Timer 1     : Starting
13:19:37: Thread Timer 2     : Starting
13:19:37: Thread Timer 3 running.
13:19:37: Daemon setting is True on Timer 3
13:19:38: Thread Timer 3 running.
13:19:39: Thread Timer 2     : Finishing
13:19:39: Thread Timer 3 running.
13:19:40: Thread Timer 3 running.
13:19:41: Thread Timer 1     : Finishing
13:19:41: Waited until Timer 1 had finished
13:19:41: Timer3 should not be able to finish, since it is a daemon Thread
13:19:41: Thread Timer 3 running.
13:19:42: Thread Timer 3 running.
13:19:43: Thread Timer 3 running.
To infinity

这两个代码在我的计算机解释器上运行良好。

【问题讨论】:

    标签: multithreading jupyter-notebook daemon


    【解决方案1】:

    问题是正常退出处理是在所有非守护线程都消失后终止守护线程,但是当 jupyter notebook 中的单元完成执行时,没有“正常”退出处理完成。您将不得不更改您的 run 方法,以便在设置“停止”条件时它最终会返回。例如,您可以添加一个do_halt 方法,该方法设置一个将由run 检查的属性,然后执行join

    class threadLauncher3(threading.Thread):
        def __init__(self, name, delay):
            super().__init__()
            self.name = name
            self.delay = delay
            self.halt = False
    
        def run(self):
            while not self.halt:
                logging.info('Thread %s running.' %self.name)
                time.sleep(self.delay)
    
        def do_halt(self):
            self.halt = True
            self.join()
    
    # code omitted
    threadLauncherFunction3.do_halt()
    

    【讨论】: