多线程和线程池

多线程和线程池

1.基本理论
1)进程和线程

进程: 一个正在运行的应用程序就是一个进程,每个进程均运行在其专门且受保护的内存空间中

线程: 线程是进程执行任务的基本单元(一个进程中的任务都是在线程中执行的)

进程就是车间,线程就是车间里面的工人。
一个进程中默认有一个线程,这个线程叫主线程

2)线程的特点

如果在一个线程中执行多个任务,任务是串行执行的。
(当一个程序中有很多个任务的时候,如果只有一个线程,那么程序的执行效率会很低)

3)多线程

一个进程中有多个线程就是多线程
多线程执行任务的时候,多个任务可以同时(并行)执行

4)多线程原理

一个CPU同一时间只能调度一个线程,多线程其实是CPU快速的在多个线程之间切换,造成多个线程同时执行的假象
(提高CPU的利用率来提供程序执行效率)

2.Python使用多线程的方法

一个进程默认只有一个线程,这个线程叫主线程。主线程以外的线程都叫子线程。

python程序中如果需要子线程,必须创建线程类(Thread)的对象

from threading import Thread

线程对象 = Thread(target=函数,args=元组)
a.函数 - 可以是普通函数函数名,也可以是匿名函数。这个函数就是需要在子线程中执行的1任务。
b.元组 - 元组中的元素就是子线程中调用target对应的函数的时候需要的参数

from time import sleep
def download(name):
    print('开始下载')
    sleep(2)
    print('下载完毕')

# 1)创建线程对象
t1 = Thread(target=download, args=('肖生客的救赎',))
t2 = Thread(target=download, args=('霸王别姬',))
t3 = Thread(target=download, args=('阿甘正传',))


# 2)启动线程  - 让子线程调用对应的函数
# 线程对象.start()
t1.start()
t2.start()
t3.start()
print('全部完成')

基本同时完成

3.线程的等待和阻塞

上诉的逻辑中print的逻辑很明显是自上而下的,但是每个线程刚开始的时候,print就会开始执行了,导致。电影每下载完成就已经打印了print。跟我们认识的下载完成后打印不一样,因为主线程不是妨碍多线程的任务,这个时候需要让所有线程的任务全部执行完毕后才打印,就需要线程的阻塞。

语法: 线程对象.join
from threading import Thread
from time import sleep
from datetime import datetime
from random import randint


def download(name):
    print(f'{name}开始下载:{datetime.now()}')
    sleep(randint(2, 7))
    print(f'{name}下载结束:{datetime.now()}')


if __name__ == '__main__':
    # 示例1:三个电影都下载结束后打印'全部下载完成'
    t1 = Thread(target=download, args=('明日战机'))
    t2 = Thread(target=download, args=('斗罗大陆'))
    t3 = Thread(target=download, args=('独行月球'))

    t1.start()
    t2.start()
    t3.start()

    # 示例1
    # 1.子线程对象.join()    -   阻塞当前线程直到指定子线程任务完成
    t1.join()
    t2.join()
    t3.join()
    print('全部完成')
4:创建线程池
  1. 线程池 - 管理多个线程的工具
线程池工作原理:先创建指定个数的线程,然后添加多个任务(任务数量>线程数量),
让线程池中的线程去执行添加的所有任务,直到所有任务都执行完(线程池中的每个线程可能会执行多个任务)
from concurrent.futures import ThreadPoolExecutor

使用线程池需要导入的模块

1)创建线程池对象

ThreadPoolExecutor(线程数最大值)

pool = ThreadPoolExecutor(3)
2)添加任务
def download(name):
    print(f'{name}开始下载:{datetime.now()}', current_thread())
    sleep(randint(2, 7))
    print(f'{name}下载结束:{datetime.now()}')
补充:current_thread(),查看当前线程ID

添加任务的方式有两种

a.一次添加一个任务: submit(函数, 实参1, 实参2, 实参3,…)

注意:实参的数量由前面的函数在调用的时候需要的实参来决定
pool.submit(download, '肖生克的救赎')
pool.submit(download, '霸王别姬')

b.同时添加多个任务: map(函数, 参数对应的序列)

注意:使用map添加多个任务的时候,任务对应的函数必须是有且只有一个参数的函数
pool.map(download, ['V字仇杀队', '恐怖游轮', '沉默的羔羊'])
3.关闭线程池

线程池关闭后无法再添加新的任务,并且会阻塞当前线程等待整个线程池的任务都完成

语法:线程池对象.shutdown()
pool.shutdown()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值