python 有两种类型线程

  • 守护线程 (主程序退出,守护线程也会被kill)
  • 其他线程(非守护线程)

举例: 生成两个线程, 其中一个运行更久的时间,

  1. import threading
  2. import time
  3. def print_work_a():
  4. print("starting of thread: ", threading.currentThread().name)
  5. time.sleep(2)
  6. print("starting of thread: ", threading.currentThread().name)
  7. def print_work_b():
  8. print('string of thread:', threading.currentThread().name)
  9. print('string of thread:', threading.currentThread().name)
  10. a = threading.Thread(target=print_work_a, name='Thread-a')
  11. b = threading.Thread(target=print_work_b, name='Thread-b')
  12. a.start()
  13. b.start()
  14. """
  15. (pythonparallel) D:\projects\pythoncode\pythonparallel>python pythreaddemo.py
  16. starting of thread: Thread-a
  17. string of thread: Thread-b
  18. string of thread: Thread-b
  19. starting of thread: Thread-a
  20. (pythonparallel) D:\projects\pythoncode\pythonparallel>
  21. """

主线程、执行线程全部执行完毕后,才退出。
现在将 Thread-a作为守护进程。

  1. # 程序修改的部分
  2. a = threading.Thread(target=print_work_a, name='Thread-a', daemon=True)
  3. b = threading.Thread(target=print_work_b, name='Thread-b')
  4. """
  5. (pythonparallel) D:\projects\pythoncode\pythonparallel>python pythreaddemo.py
  6. starting of thread: Thread-a
  7. string of thread: Thread-b
  8. string of thread: Thread-b
  9. (pythonparallel) D:\projects\pythoncode\pythonparallel>
  10. """

主线程,与所有非守护进程全部执行完毕后,就退出了(没有等待 thread-a 守护进程执行完毕)

有些线程执行后台任务,例如发送keepalive数据包,或执行定期垃圾收集等等。这些仅在主程序运行时才有用,并且一旦其他非守护程序线程退出就可以将它们终止。

如果没有守护程序线程,您必须跟踪它们,并在程序完全退出之前告诉它们退出。通过将它们设置为守护程序线程,您可以让它们运行并忘记它们,当程序退出时,任何守护程序线程都会自动终止

daemon thread 和守护进程没什么卵关系

是的,他们主要的共同点就是都包含单词“daemon”。但非要说一点联系没有也是不对的。一般而言,被 flag 为 daemon 的线程需要长期在后台执行(比如发送心跳包、检查未读消息等),并且不需和用户直接交互,和守护进程类似。

总结

简单来说就是,本来并没有 daemon thread,为了简化程序员的工作,让他们不用去记录和管理那些后台线程,创造了一个 daemon thread 的概念。这个概念唯一的作用就是,当你把一个线程设置为 daemon,它会随主线程的退出而退出。关键点有三个:

  1. background task
  2. only useful when the main program is running
  3. ok to kill

参考

https://laike9m.com/blog/daemon-is-not-daemon-but-what-is-it,97/