Python multithreading has the same effect as the join() method in multiple processes.

Just take multithreading as an example:

First, a few concepts need to be clarified:

Knowledge 1:

When a process is started, a main thread is created by default, because threads are the smallest unit of the program’s execution flow. When multithreading is set, the main thread creates multiple child threads. In Python, by default (setDaemon(False)), the main thread completes its task and then exits. The child thread will continue to execute its own task until the end of its own task, as shown in example 1 below.

Knowledge 2:

When the setDaemon(True) method is used to set the child thread to be a daemon thread, the main thread is terminated, and the child thread may have to be stopped before its work is completed, as shown in example 2 below.

Knowledge 3:

At this point, the role of join is highlighted. What join completes is thread synchronization, that is, the main thread task enters the blocking state at the place where the join function is set and waits for the completion of other child threads before the main thread starts to execute until it terminates, as shown in the following three examples.

Knowledge 4:

Join takes a timeout argument:

  • When there is a setup daemon thread, meaning that the main thread waits for the child threadtimeoutWill kill the child thread and exit the program. So, if there are 10 child threads, the total wait time is the sum of each timeout. In simple terms, one for each child threadtimeoutTime, let him execute, when the time is up, whether the mission is complete or not, directly kill.
  • When no daemon thread is setThe main thread will waittimeoutWhen the time is up, the main thread ends, but does not kill the child thread, the child thread can continue to execute, until the child thread is finished, the program exits.

One: Python multithreading default

import threading
import time

def run() :
    time.sleep(2)
    print('The current thread name is:', threading.current_thread().name)
    time.sleep(2)


if __name__ == '__main__':

    start_time = time.time()

    print('This is the main thread:', threading.current_thread().name)
    thread_list = []
    for i in range(5):
        t = threading.Thread(target=run)
        thread_list.append(t)

    for t in thread_list:
        t.start()

    print('End of main thread! ' , threading.current_thread().name)
    print('Total time:', time.time()-start_time)
Copy the code

The execution results are as follows:

Key:

  • Timing is how long it takes to time the main thread, when the main thread ends, to print the main thread.
  • After the completion of the main thread, the main thread ends, and the child thread continues to execute its own task, until all the tasks of the child thread are finished, the program ends.

Two: set the daemon thread

import threading
import time

def run() :

    time.sleep(2)
    print('The current thread name is:', threading.current_thread().name)
    time.sleep(2)


if __name__ == '__main__':

    start_time = time.time()

    print('This is the main thread:', threading.current_thread().name)
    thread_list = []
    for i in range(5):
        t = threading.Thread(target=run)
        thread_list.append(t)

    for t in thread_list:
        t.setDaemon(True)
        t.start()

    print('Main thread is over! ' , threading.current_thread().name)
    print('Total time:', time.time()-start_time)
Copy the code

Note: Make sure that setDaemon() executes as follows before start() :

Key points:
  • Obviously, after the main thread ends, the entire program exits before the child thread can execute.

Three: The role of join

import threading
import time

def run() :

    time.sleep(2)
    print('The current thread name is:', threading.current_thread().name)
    time.sleep(2)


if __name__ == '__main__':

    start_time = time.time()

    print('This is the main thread:', threading.current_thread().name)
    thread_list = []
    for i in range(5):
        t = threading.Thread(target=run)
        thread_list.append(t)

    for t in thread_list:
        t.setDaemon(True)
        t.start()

    for t in thread_list:
        t.join()

    print('Main thread is over! ' , threading.current_thread().name)
    print('Total time:', time.time()-start_time)
Copy the code

The execution results are as follows:

Key points:
  • As you can see, the main thread waits for all child threads to finish before the main thread itself terminates and the program exits.

An unexpected exit of the main program

Using b.jin () in thread A means that thread A is blocked at the call to join() and is waiting for thread B to complete before it can continue

import threading
import time


def child_thread1() :
    for i in range(10):
        time.sleep(1)
        print('child_thread1_running... ')


def child_thread2() :
    for i in range(5):
        time.sleep(1)
        print('child_thread2_running... ')


def parent_thread() :
    print('parent_thread_running... ')
    thread1 = threading.Thread(target=child_thread1)
    thread2 = threading.Thread(target=child_thread2)
    thread1.setDaemon(True)
    thread2.setDaemon(True)
    thread1.start()
    thread2.start()
    thread2.join()
    1/0
    thread1.join()
    print('parent_thread_exit... ')


if __name__ == "__main__":
    parent_thread()
Copy the code

Output:

parent_thread_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
Traceback (most recent call last):
  File "E:/test_thread.py", line 31.in <module>
    parent_thread()
  File "E:/test_thread.py", line 25.in parent_thread
    1/0
ZeroDivisionError: integer division or modulo by zero
Copy the code

The main thread blocks on thread2.join() and waits for thread2 to finish before executing the next sentence

1/0 causes the main thread to exit with an error, and thread1 is set to daemon=True, so if the main thread exits unexpectedly, thread1 will terminate immediately. Thread1.join () is not executed by the main thread