Python基础知识(二)

4 阅读3分钟

线程

使用thread创建线程

import os, time
from threading import get_native_id, Thread, RLock

def speak(lock):
    for index in range(5):
        with lock:
            print(f'我是{index}正在说话,当前进程是{os.getpid()},线程编号是{get_native_id()}')
        time.sleep(1)

def study(lock):
    for index in range(5):
        with lock:
            print(f'我是{index}正在学习,当前进程是{os.getpid()},线程编号是{get_native_id()}')
        time.sleep(1)


if __name__ == '__main__':
    print(f'-----start-----当前进程是{os.getpid()},线程编号是{get_native_id()}')
    # Thread的参数:
    # group: 默认值为 None(应当始终为None)
    # target: 子线程要执行的可调用对象,默认值为None。
    # name: 线程名称,默认为None。如果设置为None,Python会自动分配名字
    # args: 给target传的位置参数(元组).
    # kwargs:给target 传的关键字参数(字典)
    # daemon:标记线程是否为守护线程,取值为布尔值(默认为 None)

    lock = RLock()
    # 使用 Thread创建线程对象
    t1 = Thread(target=speak, args=(lock, ))
    t2 = Thread(target=study, args=(lock,))

    # 调用线程对象的start方法,会立刻将该线程交由操作系统进行调度
    t1.start()
    t2.start()

    # 让主线程等t1,t2线程执行完毕后,主线程再继续执行
    t1.join()
    t2.join()

    print('-----end-----')

继承thread创建线程

import os, time
from threading import get_native_id, Thread, RLock

class SpeakThread(Thread):
    def __init__(self, lock):
        super().__init__()
        self.lock = lock

    def run(self):
        for index in range(5):
            with self.lock:
                print(f'我是{index}正在说话,当前进程是{os.getpid()},线程编号是{get_native_id()}')
            time.sleep(1)

class StudyThread(Thread):
    def __init__(self, lock):
        super().__init__()
        self.lock = lock

    def run(self):
        for index in range(5):
            with self.lock:
                print(f'我是{index}正在学习,当前进程是{os.getpid()},线程编号是{get_native_id()}')
            time.sleep(1)


if __name__ == '__main__':
    print(f'-----start-----当前进程是{os.getpid()},线程编号是{get_native_id()}')
    lock = RLock()
    # 继承 Thread类创建线程对象
    t1 = SpeakThread(lock)
    t2 = StudyThread(lock)

    # 调用线程对象的start方法,会立刻将该线程交由操作系统进行调度
    t1.start()
    t2.start()

    # 让主线程等t1,t2线程执行完毕后,主线程再继续执行
    t1.join()
    t2.join()

    print('-----end-----')

线程池

1、创建线程池执行器,使用 submit 方法提交任务,使用 shutdown 方法等待任务完成

import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import get_native_id, RLock

# 1、创建线程池执行器,使用 submit 方法提交任务,使用 shutdown 方法等待任务完成
def work(n, lock):
    with lock:
        print(f'我是线程{n},我正在工作{get_native_id()}')
    time.sleep(1)

if __name__ == '__main__':
    print('-----start-----')
    # 创建线程池执行器
    executor = ThreadPoolExecutor(3)
    # 创建线程锁
    lock = RLock()
    # 使用 submit 方法提交任务(submit 方法是异步的,只负责提交任务,不会阻塞主线程)
    executor.submit(work, 1, lock)
    executor.submit(work, 2, lock)
    executor.submit(work, 3, lock)
    executor.submit(work, 4, lock)
    executor.submit(work, 5, lock)
    executor.submit(work, 6, lock)
    executor.submit(work, 7, lock)

    # shutdown 方法的作用:不再接收新的任务
    # wait=True:阻塞主线程,等待线程池中所有任务执行完毕 
    executor.shutdown(wait=True)
    print('-----end-----')

2 获取子进程执行后的返回结果(Future类的实例对象 + result方法)

def work(n):
    print(f'我是线程{n},我正在工作{get_native_id()}')
    time.sleep(1)
    return f'我是线程{n}的结果'

if __name__ == '__main__':
    print('-----start-----')
    # 创建线程池执行器
    executor = ThreadPoolExecutor(3)
    # submit提交任务
    features = [executor.submit(work, index) for index in range(1,8)]    

    # shutdown 阻塞主线程
    executor.shutdown(wait=True)

    # 打印结果
    for f in features:
        print(f.result())

    print('-----end-----')

3 as_completed 按完成顺序获取结果

def work(n, lock):
    with lock:
        print(f'我是线程{n},我正在工作{get_native_id()}')
    if n == 1:
        time.sleep(8)
    elif n == 2:
        time.sleep(10)        
    else:
        time.sleep(1)
    return f'我是线程{n}的结果'

if __name__ == '__main__':
    print('-----start-----')
    # 创建线程池执行器
    executor = ThreadPoolExecutor(3)
    # 创建锁
    lock = RLock()
    # submit提交任务
    features = [executor.submit(work, index, lock) for index in range(1,8)]   

    # 收集每个线程返回的结果
    results = [] 
    for f in as_completed(features):
        results.append(f.result())

    # shutdown 阻塞主线程
    executor.shutdown(wait=True)

    # 打印结果
    print(results)

    print('-----end-----')

4 使用 add_done_callback 方法,为任务添加完成时的回调函数