线程----join()详解

今天突然觉得join函数好陌生 忘了是干嘛了的,所得花点回顾了一下。

了解线程的知识    请点 --->>   了解更多的线程知识

想要彻底了解join()就要先理解守护线程:

         守护线程的工作方式类似服务器,只要没有客户端发来请求,就一直运行并且保持空闲,很像是后台。threading模块建立的线程除了守护线程之外,其余的线程都会在主线程结束之前结束掉。也就是说一般会先解决非守护线程的,所以相比而言,守护线程好像就“没那么重要”。设置守护线程使用,要在线程启动之前就设置好
 

接下来是join():

 threading模块中join()的作用是为了防止子线程没结束主线程就先结束了,join()对于创建的普通的线程(除了守护线程)是没有多大作用的,有跟没有一样,都是要等到子线程结束后才会执行主线程。守护线程相比普通的线程显得“没有那么重要”,所以主线程一般不等它结束就先结束了。如果是作为守护线程使用join(),那么就会等待守护线程结束后才会执行主线程。
 

下面请看非守护线程使用join(),不使用join(),以及守护线程使用join()和不使用的具体实例

1.非守护线程不使用join()

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))
    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看到 :  子线程  还没有全部执行结束,主线程就先执行了,然后再回来执行  子线程  到结束。

2.守护线程不使用join()

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))

    t1.setDaemon(True)    # 设置t1为守护线程
    t2.setDaemon(True)    # 设置t2为守护线程

    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看到:守护的子线程还没有执行结束,主线程就先执行完了,并且主线程也不再回头 执行子线程了

(突然觉得守护线程的地位好低,有木有,被人抛弃了)

3.非守护线程使用join():

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))
    t1.start()
    t2.start()
    t1.join()

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看出:当给t1 t2 任意一个  子线程  加上join()之后,主线程  要等到  子线程  全部执行完,主线程才去执行。(地位超级高)

4.守护线程加上join():

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))
    t1.setDaemon(True)
    t2.setDaemon(True)
    t1.start()
    t2.start()
    t1.join()

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看出:给  守护线程  加上join()后, 主线程需要等到   守护线程  全部执行完毕后,主线程才执行。(守护线程的地位提高了好多)

那要是给join()加上参数呢? 例如:join(2)

加上参数2的意思是,主线程就给子线程2s的执行时间,2s一到,不管你子线程执行结束了没有,我主线程都要执行

5.  join(2)的 非守护线程

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))

    t1.start()
    t2.start()
    t1.join(2)

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看出:2s时间一到,主线程就开始执行了,不过主线程执行完毕后,又回头来继续执行子线程到结束。

那么守护线程呢?

6.join(2)的守护线程:

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))
    t1.setDaemon(True)
    t2.setDaemon(True)
    t1.start()
    t2.start()
    t1.join(2)

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看出: 2s一到主线程开始执行,主线程执行结束后,也不再回去执行子线程了。(守护线程又被抛弃了)

7.join()位置带来不同结果:

我们给t1线程加上join(),放在了t2线程的前面:

from threading import Thread
import time

def dance(num):
    for i in range(num):
        print("正在跳舞", i)
        time.sleep(2)

def sing(num):
    for i in range(num):
        print("正在唱歌", i)
        time.sleep(2)

def main():
    t1 = Thread(target=dance, args=(3,))
    t2 = Thread(target=sing, args=(3,))
    t1.start()

    t1.join(2)

    t2.start()

if __name__ == '__main__':
    main()
    print("程序结束了")

执行结果:

可以看出:t1全部执行完毕后,接下来主线程开始执行,最后是t2执行

个人总结:join()的作用其实就是给所添加的子线程一个优先执行的权利,等加上join()的子线程执行完毕之后,其他线程再执行。

而守护线程和普通线程区别就是:

守护线程会随着非守护线程结束而结束(比如主线程和其他副线程)。

守护线程:只要主线程执行完毕,不等其他线程,就退出程序

就是等待非守护线程执行完毕就退出。

猜你喜欢

转载自blog.csdn.net/weixin_43567965/article/details/88934586
今日推荐