python中多线程:线程插队方法join详解、线程停止、通过变量来让线程停止

发布于:2025-06-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

线程插队方法join详解

import threading
import time

# 下载任务
def thread_body(movie_name):
    t = threading.current_thread()
    # 模拟耗时操作
    for i in range(5):
        print(f'{t.name} 线程正在下载{movie_name}中')
        time.sleep(1)

# 子线程每个线程都是独立运行的,线程1不会影响线程2,同理线程2也不会影响线程3,互不影响
if __name__ == '__main__':
    # target=thread_body() 不是传递参数名称,是调用方法;
    # args是元组类型,参数只有一个的话,一定要在该元素之后添加逗号,否则会认为是一个字符串类型
    t1 = threading.Thread(target=thread_body, args = ("三体一:地球往事",), name="下载任务1")
    t2 = threading.Thread(target=thread_body, args = ("三体二:黑暗森林",), name="下载任务2")
    t3 = threading.Thread(target=thread_body, args = ("三体三:死神永生",), name="下载任务3")
    # 启动线程
    t1.start()
    t2.start()
    t3.start()

    print(f'{threading.current_thread()} 主线程正在执行用户实时操作')

执行结果:
在这里插入图片描述
可以看到的现象就是:主线程都结束了,但是子线程还么有结束,这就会有可能主线程再子线程结束前结束。

需求:主线程需要等子线程全部完成才能结束,所以子线程需要cut line 执行,在python的thread中通过join即可完成这种插队操作,示例代码。

import threading
import time

# 下载任务
def thread_body(movie_name):
    t = threading.current_thread()
    # 模拟耗时操作
    for i in range(5):
        print(f'{t.name} 线程正在下载{movie_name}中')
        time.sleep(1)

# 子线程每个线程都是独立运行的,线程1不会影响线程2,同理线程2也不会影响线程3,互不影响
if __name__ == '__main__':
    # target=thread_body() 不是传递参数名称,是调用方法;
    # args是元组类型,参数只有一个的话,一定要在该元素之后添加逗号,否则会认为是一个字符串类型
    t1 = threading.Thread(target=thread_body, args = ("三体一:地球往事",), name="下载任务1")
    t2 = threading.Thread(target=thread_body, args = ("三体二:黑暗森林",), name="下载任务2")
    t3 = threading.Thread(target=thread_body, args = ("三体三:死神永生",), name="下载任务3")
    # 启动线程
    t1.start()
    t2.start()
    t3.start()
    # 需求:主线程需要等子线程全部完成才能结束,所以子线程需要cut line 执行
    t1.join()
    t2.join()
    t3.join()
    print(f'{threading.current_thread()} 主线程正在执行用户实时操作')

t1、t2、t3插队后的执行结果
在这里插入片描述
现象可以说明:join相当于对当前线程产生阻塞现象,阻止当前线程继续向下执行。要想让子线程可以正常执行完毕,需要让子线程插队到主线程之前,保证子线程能完全执行完。
使用案例:例如50个线程下载50张图片,这时候需要每个线程都要结束之后才能结束主线程,此时需要遍历子线程列表,让每一个子线程对象插队到主线程之前执行。

import threading
import time

# 下载任务
def thread_body(movie_name):
    t = threading.current_thread()
    # 模拟耗时操作
    for i in range(5):
        print(f'{t.name} 线程正在下载{movie_name}中')
        time.sleep(1)

# 子线程每个线程都是独立运行的,线程1不会影响线程2,同理线程2也不会影响线程3,互不影响
if __name__ == '__main__':
    # 创建一个用于存储下载任务子线程的列表
    download_threads : list[threading.Thread] = list()  #空列表
    # 参数列表:参数元组类型数据
    download_agrs = ("三体一:地球往事", "三体二:黑暗森林", "三体三:死神永生")

    # 创建子线程对象
    for argument in download_agrs:
        # 创建子线程
        download_thread = threading.Thread(target=thread_body, args=(argument,))
        # 将子线程添加到列表中
        download_threads.append(download_thread)
        # 启动子线程
        download_thread.start()

    for download_thread in download_threads:
        # 子线程插队行为
        download_thread.join()

    print(f'主线程执行完了')

执行结果
在这里插入图片描述

线程停止:用一个子线程控制另一个子线程的运行状态。

import threading
import time

# 全局变量
isRunning = True


# 工作体
def working_body():
    # 死循环
    while isRunning:
        print('工作线程正在执行中...')
        time.sleep(1)
    print('工作线程执行完毕了...')


# 控制线程
def control_body():
    # 申明全局变量
    global isRunning
    # 死循环
    while isRunning:
        # 接收用户指令但是没有提示语
        command = input()
        # 如果是退出,就修改为false,控制其结束
        if command == 'exit':
            isRunning = False
        else:
            print(f'{command = }')


if __name__ == '__main__':
    # 主线程
    # 1.创建子线程
    working_thread = threading.Thread(target=working_body, name='工作线程')
    working_thread.start()

    # 创建一个子线程,用于控制工作线程的执行状态
    control_thread = threading.Thread(target=control_body, name='控制线程')
    control_thread.start()

    print('主线程执行完毕!!')

执行结果
可以通过变量来控制线程自身的运行状态,甚至是其他线程的运行状态
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到