8-2-3python语法基础-并发编程-进程和线程对比学习:join和setDaemon,守护进程和守护线程

前言

进程和线程,有很多地方非常类似,包括使用的方法也很多相同的,
所以我决定放到一起对比学习,
这一篇,专门对比:

  • 进程和守护进程,
  • 线程和守护线程,
  • join和setDaemon

进程和守护进程

daemon=True

import multiprocessing
import time


def f():
    print("子进程1")
    time.sleep(3)
    print("子进程1运行结束")


if __name__ == '__main__':
    # 定义一个子进程
    use = multiprocessing.Process(target=f)
    # 将子进程设置为守护进程
    use.daemon = True
    # 调用子进程
    use.start()
    print("程序运行结束")

输出结果:
程序运行结束

所以主进程结束,不管子进程有没有运行完,子进程也结束了,

daemon=False

import multiprocessing
import time


def f():
    print("子进程1")
    time.sleep(3)
    print("子进程1运行结束")


if __name__ == '__main__':
    # 定义一个子进程
    use = multiprocessing.Process(target=f)
    # 将子进程设置为守护进程
    use.daemon = False
    # 调用子进程
    use.start()
    print("程序运行结束")

输出结果:
程序运行结束
子进程1
子进程1运行结束

所以主进程虽然结束了,但是子进程还在运行,直到结束,也就是这个时候不管主进程有没有结束,子进程都会运行完才会结束
其实默认就是False,写不写这一句,运行结果都是一样的,

join()


import multiprocessing
import time


def f():
    print("子进程1")
    time.sleep(3)
    print("子进程1运行结束")


if __name__ == '__main__':
    # 定义一个子进程
    use = multiprocessing.Process(target=f)
    # 将子进程设置为守护进程
    # 调用子进程
    use.start()
    use.join()
    print("程序运行结束")

输出结果:
子进程1
子进程1运行结束
程序运行结束

所以主进程会等待所有的子进程都结束了,才会继续往下运行,
一般实际使用,都是daemon=True,并且加入join,这样既可以保证主进程最后运行,也可以保证主进程运行完了, 子进程都结束了,不会出现僵尸进程,

线程和守护线程

setDaemon方法

  • 当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,

  • setDaemon这个方法,此方法是将子线程设置为守护线程。setDaemon放在start方法之前,可以理解为先设置完后再进行调用。

  • 当主线程结束时根据子线程daemon(设置thread.setDaemon(True)),其中括号中可以填写True 或者False,属性值的不同,可能会发生下面的两种情况之一:

第一种情况:setDaemon(True)

  • 如果某个子线程的daemon属性为True,
  • 设置为true,意思就是把主线程A设置为守护线程,
  • 这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.
    注意:
  • 1、守护线程会被其他最后一个线程或主线程终止。监听谁 就把谁设置守护线程
    最常见的连用方式 thr.setDaemon(True), 后面thr.join() 注意不用加时间。或者加一个超时时间,超时时间一到主线程执行,执行结束后,进程自动关闭守护子线程。
import threading
import time


def f():
    print("子线程1")
    time.sleep(3)
    print("子线程1运行结束")


if __name__ == '__main__':
    # 定义一个子线程
    use = threading.Thread(target=f)
    # 将子线程设置为守护线程
    use.setDaemon(True)
    # 调用子线程
    use.start()
    print("程序运行结束")

输出结果:
子线程1
程序运行结束

所以不会执行子线程剩下的部分了,这就是主线程结束,子线程不管有没有完成,都结束,比较暴力,

第二种情况:setDaemon(False)

  • 如果某个子线程的daemon属性为False,
  • 主线程结束时会检测该子线程是否结束,如果该子线程还在运行,则主线程会等待它完成后再退出;
  • 其实你如果不写setDaemon(False),默认就是这样的,所以如果是False,写不写这一句都一样,

注意:

  • 1、主线程退出,子线程还可以在跑。线程之间都无关
import threading
import time


def f():
    print("子线程1")
    time.sleep(3)
    print("子线程1运行结束")


if __name__ == '__main__':
    # 定义一个子线程
    use = threading.Thread(target=f)
    # 将子线程设置为守护线程
    use.setDaemon(False)
    # 调用子线程
    use.start()
    print("程序运行结束")

输出结果:
子线程1
程序运行结束
子线程1运行结束

所以这种情况,就是主线程结束了,但是子线程还在执行一直到结束,

第三种情况:join的使用

import threading
import time


def f():
    print("子线程1")
    time.sleep(3)
    print("子线程1运行结束")


if __name__ == '__main__':
    # 定义一个子线程
    use = threading.Thread(target=f)
    # 将子线程设置为守护线程
    # 调用子线程
    use.start()
    use.join()
    print("程序运行结束")

输出结果:
子线程1
子线程1运行结束
程序运行结束

  • 所以你发现了,主线程会等待子线程结束了才会继续执行,

join和setDaemon(True)setDaemon(False)对比

场景 setDaemon(True) setDaemon(False) join
主线程结束了子线程是否继续运行? ×
主线程等待子线程全部结束才运行 × ×

进程和线程的使用区别

就是进程是使用属性赋值的方式,实现守护进程,
线程是使用方法的方法,实现的守护进程,

所以你明白为什么要对比学习了吧,
这种对比学习,可以让你印象更加的深刻,

posted @ 2022-05-03 13:11  技术改变命运Andy  阅读(500)  评论(0编辑  收藏  举报