python多线程编程 join

Posted 谢小小XH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python多线程编程 join相关的知识,希望对你有一定的参考价值。

一.背景

直接从一个例子来说吧.

import time
import threading

def fun():
    for i in range(5):
        time.sleep(1)
        print("hello word")

def main():
    thread_1 = threading.Thread(target=fun, name="thread_1")
    thread_1.start()
    print("active thread num: ", threading.active_count())
    print("activa threads list: ",threading.enumerate())
    print("current activate thread: ",threading.current_thread())
    print("active thread num: ", threading.active_count())

if __name__=="__main__":
    main()

结果:

active thread num:  2
activa threads list:  [<_MainThread(MainThread, started 16084)>, <Thread(thread_1, started 16424)>]
current activate thread:  <_MainThread(MainThread, started 16084)>
active thread num:  2
hello word
hello word
hello word
hello word
hello word

结果就是主线程都结束了,新加的那个线程还没有开始跑起来.这显然不是我们想要的.

那么有时候我们希望我们定义的一个线程能够先跑完然后再跑这个线程后面的内容,应该怎么办呢?

在上面介绍函数的时候就已经说过Thread类中有函数叫做join()了,他的作用就是等到这个线程结束,然后才开始其他的内容.把上面的例子非常简单的改一下,如下

import time
import threading

def fun():
    for i in range(5):
        time.sleep(1)
        print("hello word")


def main():
    thread_1 = threading.Thread(target=fun, name="thread_1")
    thread_1.start()
    thread_1.join()
    print("active thread num: ", threading.active_count())
    print("activa threads list: ",threading.enumerate())
    print("current activate thread: ",threading.current_thread())
    print("active thread num: ", threading.active_count())

if __name__=="__main__":
    main()

结果:

hello word
hello word
hello word
hello word
hello word
active thread num:  1
activa threads list:  [<_MainThread(MainThread, started 16604)>]
current activate thread:  <_MainThread(MainThread, started 16604)>
active thread num:  1

简单到只需要在start之后加一句thread_1.join() 就行了.

二.多个线程

这里说一下稍微复杂一点的例子,起一个抛砖引玉的作用.

import time
import threading

def fun():
    for i in range(5):
        time.sleep(2)
        print("hello word")

def fun_2():
    for i in range(5):
        time.sleep(1)
        print(i*10)

def main():
    thread_1 = threading.Thread(target=fun, name="thread_1")
    thread_1.start()
    thread_1.join()
    thread_2=threading.Thread(target=fun_2,name="thread_2")
    thread_2.start()
    thread_2.join()
    print("active thread num: ", threading.active_count())
    print("activa threads list: ",threading.enumerate())
    print("current activate thread: ",threading.current_thread())
    print("active thread num: ", threading.active_count())

if __name__=="__main__":
    main()

这段代码,是在最开始的代码的基础上改了很小一些地方出来.只是把fun()打印的时间延迟到2秒.然后新加了另外一个线程thread_2,这个线程调用的函数是每1秒打印一个数字.

结果:

hello word
hello word
hello word
hello word
hello word
0
10
20
30
40
active thread num:  1
activa threads list:  [<_MainThread(MainThread, started 16544)>]
current activate thread:  <_MainThread(MainThread, started 16544)>
active thread num:  1

结果很简单,如我们预期的那样,通俗一点说,就是先把thread_1 要搞的事情搞完,然后再thread_2要搞的事情搞完,最后结束.但是,这种方式和单线程有区别?

另外举一个例子,这样可以直观看到多线程的作用.

import time
import threading

num=[1,2,3,4,5,6,7,8,9,10]


def fun():
    for i in range(5):
        time.sleep(3)
        num[i]-=1
        #print("hello word")

def fun_2():
    for i in range(5,10):
        time.sleep(1)
        num[i]-=1
        #print(i*10)

def main():
    print(num)
    thread_1 = threading.Thread(target=fun, name="thread_1")
    thread_1.start()

    thread_2=threading.Thread(target=fun_2,name="thread_2")
    thread_2.start()

    print("active thread num: ", threading.active_count())
    print("activa threads list: ",threading.enumerate())
    print("current activate thread: ",threading.current_thread())
    print("active thread num: ", threading.active_count())
    print(num)

if __name__=="__main__":
    main()

这段代码通俗的说,就是两个工人(线程)分别修改数组的一半,使得数组内容减去1.这里没有加join(),数组都还没有修改,程序就结束了.

结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
active thread num:  1
activa threads list:  [<_MainThread(MainThread, started 15996)>]
current activate thread:  <_MainThread(MainThread, started 15996)>
active thread num:  1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

所以,最好的方式就是把这两个thread都加上join(),放在后面.等他们跑完.

import time
import threading

num=[1,2,3,4,5,6,7,8,9,10]


def fun():
    for i in range(5):
        time.sleep(3)
        num[i]-=1
        #print("hello word")

def fun_2():
    for i in range(5,10):
        time.sleep(1)
        num[i]-=1
        #print(i*10)

def main():
    print(num)
    thread_1 = threading.Thread(target=fun, name="thread_1")
    thread_1.start()

    thread_2=threading.Thread(target=fun_2,name="thread_2")
    thread_2.start()

    thread_2.join()
    thread_1.join()

    print("active thread num: ", threading.active_count())
    print("activa threads list: ",threading.enumerate())
    print("current activate thread: ",threading.current_thread())
    print("active thread num: ", threading.active_count())
    print(num)

if __name__=="__main__":
    main()

结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
active thread num:  1
activa threads list:  [<_MainThread(MainThread, started 15648)>]
current activate thread:  <_MainThread(MainThread, started 15648)>
active thread num:  1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

以上是关于python多线程编程 join的主要内容,如果未能解决你的问题,请参考以下文章

Python并发编程04/多线程

彻底理解Python多线程中的setDaemon与join配有GIF示意

多任务-python实现-进程,协程,线程总结(2.1.16)

Python爬虫编程思想(136):多线程和多进程爬虫--Thread类与线程函数

Python爬虫编程思想(136):多线程和多进程爬虫--Thread类与线程函数

python多线程的几种方法