python线程池与多线程的区别-LMLPHP

一. 线程与多线程

进程: 一个程序执行时,可以称之为一个进程,其包含运行中的程序和程序所使用的内存和系统资源.一个进程由多个线程所组成.

线程: 线程是程序中的一个执行流,每个线程都有自己的专有寄存器,同时代码区是共享的.不同的线程可以执行同样的函数.

多线程: 多线程是指程序中包含多个执行流,也即是一个程序中可以同时运行多个不同的线程来执行不同的任务,允许单个程序创建多个并行执行的线程来完成各自的任务.

多线程最大的好处: 提高CPU利用率( 尤其适用于 I/O密集型程序 , 速度提升特别明显)

进程与线程的区别:

做个简单的比喻:进程=火车,线程=车厢

线程在进程下行进(单纯的车厢无法运行)

一个进程可以包含多个线程(一辆火车可以有多个车厢)

不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)

同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)

进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)

进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)

进程可以拓展到多机,进程最多适合多核(不同火车可以开在多个轨道上,同一火车的车厢不能在行进的不同的轨道上)

进程使用的内存地址可以上锁,即一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。(比如火车上的洗手间)-"互斥锁"

进程使用的内存地址可以限定使用量(比如火车上的餐厅,最多只允许多少人进入,如果满了需要在门口等,等有人出来了才能进去)-“信号量”

二. 多线程之 threading 类

threading类是最常用的多线程模块.创建线程的方法如下代码:

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, 
daemon=None)
登录后复制

group:默认为None.

target:要执行的函数名, 记得不要带函数的括号.

name:线程名称,默认为'Thread-N'形式.

args:在参数target中传入的可调用对象的参数元组.

kwargs:在参数target中传入的可调用对象的关键字参数字典.

daemon:守护模式属性,默认为None.

线程对象的重要方法:

start(): 开启线程.它将使得run()方法在一个独立的线程中被调用.

run(): 此方法代表线程活动.

join(timeout=None): 让当前调用者线程等待,直到线程结束.

daemon: 表示该线程是否为守护线程, True或者False.

创建多线程实例:

import random
import threading
import time
def awesome_function(name):
wait_time = random.randint(1, 10)
print('current thread name is :{0} and wait {1} s'.format(name, 
wait_time))
time.sleep(wait_time)
print('thread {} finished.'.format(name))
if __name__ == '__main__':
for i in range(0, 3):
t = threading.Thread(target=awesome_function, args=(i,))
t.start()
登录后复制

可以先看一下我录制的运行结果:

上面例子开启了3个线程,3个线程并发执行任务,先完成任务的线程(time.sleep最短的)先输出结果.

三. 更好用的线程池类ThreadPoolExecutor

启动一个新线程的开销非常大,因为它涉及与操作系统的交互.在这种情况下,使用线程池可以很好地提升程序性能,尤其是当程序中需要创建大量生存期很短暂的线程时更应该考虑使用线程池.

线程池在系统启动时即创建大量空闲的线程,程序只要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它.当该函数执行结束后,该线程并不会死亡,而是再次返回到线程池中变成空闲状态,等待下一个函数.同时,使用线程池可以有效地控制系统中并发线程的数量.当系统中包含有大量的并发线程时,会导致系统性能急剧下降,甚至导致Python解释器崩溃,而线程池的最大线程数参数可以控制系统中并发线程的数量不超过此数.

现在主流使用的线程池是concurrent.futures模块中的ThreadPoolExecutor:

import random
import time
from concurrent.futures import ThreadPoolExecutor
def awesome_function(name):
wait_time = random.randint(1, 10)
print('current thread name is :{0} and wait {1} s'.format(name, 
wait_time))
time.sleep(wait_time)
print('thread {} finished.'.format(name))
if __name__ == '__main__':
with ThreadPoolExecutor(max_workers=3) as t:
for i in range(0, 3):
t.submit(awesome_function, i)
登录后复制

运行结果录制如下:

创建一个最大容纳数量为3的线程池对象,通过submit提交执行的函数到线程池中,若线程池中的某个线程(thread 2)执行完成,则把空闲的线程(thread 3)放入到池子中,依次类推,直到所有线程执行完成则程序结束。

以上就是python线程池与多线程的区别的详细内容,更多请关注Work网其它相关文章!

08-22 13:26