Python - 多线程

基本使用

"""
线程的基本使用:
 sub_thread = threading.Thread(target=xxx)
 xxx: 线程任务
"""
import threading


def singe():
    """任务一"""
    for v in range(5):
        print('正在唱歌。。。。')

def dance():
    """任务二"""
    for v in range(5):
        print('正在跳舞。。。')

if __name__ == '__main__':
    # 创建线程类,指定多线成任务
    # 注意指定的函数没有括号
    thread_singe = threading.Thread(target=singe)

    thread_dance = threading.Thread(target=dance)
    # 启动多线程
    thread_singe.start()
    thread_dance.start()

获得线程数量和当前线程名称

"""
threading.current_thread() : 获得当前活跃的名称
threading.enumerate(): 返回当前活跃线程数
"""
import threading
import time


def singe():
    """任务一"""
    for v in range(5):
        print(f'{threading.current_thread()} 正在唱歌。。。。')
        time.sleep(0.2)


def dance():
    for v in range(5):
        print(f'{threading.current_thread()}正在跳舞。。。')
        time.sleep(0.2)


if __name__ == '__main__':

    # 创建线程类,指定多线成任务
    # 注意指定的函数没有括号
    thread_singe = threading.Thread(target=singe)

    thread_dance = threading.Thread(target=dance)
    # 启动多线程
    thread_singe.start()
    thread_dance.start()

    while True:
        thread_list = threading.enumerate()  # 返回当前活跃的线程列表
        thread_num = len(thread_list) # 活跃线程数量
        print(f'当前活跃的线程数量为{thread_num}')

        if thread_num == 1:
            break

        time.sleep(0.2)

多线程函数传参

import threading

def singe(a, b, c):
    """任务一"""
    print(f'a={a}, b={b}, c={c} ')
    for v in range(5):
        print('正在唱歌。。。。')

if __name__ == '__main__':

    # 传参方式一:
    # thread_singe = threading.Thread(target=singe, args=(10, 20, 30))
    # 传参方式二:
    # thread_singe = threading.Thread(target=singe, kwargs={'a': '10', 'b': '20', 'c': '30'})
    # 传参方式三:
    thread_singe = threading.Thread(target=singe, args=(10,), kwargs={'c': '20', 'b': '30'})

    # 启动多线程
    thread_singe.start()

守护线程(后台线程)

主线程退出后,子线程也要同时退出。设置方式 t.daemon = True 或者 t = threading.Thread(target=work1, daemon=True),默认是False,也就是主线程结束后,子线程依然在执行

作用:

如果有一个线程必须设置为无限循环,那么该线程不结束,意味着整个python程序就不能结束,那为了能够让python程序正常退出,将这类无限循环的线程设置为守护线程,当程序当中仅仅剩下守护线程时,python程序就能够正常退出,不必关心这类线程是否执行完毕。典型的守护线程GC 垃圾收集器

import threading
import time

def work1():
    for x in range(10):
        print('work1.......')
        time.sleep(0.5)

if __name__ == '__main__':
    t = threading.Thread(target=work1, daemon=True)
    # t.daemon = True 也可以设置守护线程
    t.start()

    time.sleep(3)
    print('主线程结束....')
    exit()

自定义线程类

并发:当前任务数大于CPU核心数
并行:当前任务数小于等于CPU核心数

"""

1. 继承threading.Thread 类
2. 重写父类的run方法
3. 调用start方法启动子线程
"""

import threading
import time

class MyThread(threading.Thread):

    def run(self) -> None:
        for tmp in range(5):
            print(f'sub thread{self.name} run....')
            time.sleep(0.5)

if __name__ == '__main__':
    my_thread = MyThread()
    my_thread.start()
    
    print(threading.current_thread().name)

互斥锁

import threading
import time

num = 0

"""
1.创建互斥锁: lock = threading.Lock(),注意需要放在创建线程之前
2.lock.acquire(): 请求锁
3.lock.release(): 释放锁
"""

def work1():
    global num

    for _ in range(1000000):
        lock.acquire()
        num += 1
        lock.release()
    print(f'{threading.current_thread().name} num is {num}')


def work2():
    global num

    for _ in range(1000000):
        lock.acquire()
        num += 1
        lock.release()

    print(f'{threading.current_thread().name} num is {num}')


if __name__ == '__main__':
    lock = threading.Lock()
    t1 = threading.Thread(target=work1)
    t2 = threading.Thread(target=work2)
    t1.start()
    t2.start()

    # 确保子线程执行完毕,才执行主线程
    while len(threading.enumerate()) != 1:
        time.sleep(1)

    print(f'{threading.current_thread().name} num is {num}')

# out:
"""
Thread-1 (work1) num is 1720405
Thread-2 (work2) num is 2000000
MainThread num is 2000000
"""
posted @ 2022-01-19 21:05  chuangzhou  阅读(34)  评论(0编辑  收藏  举报