多线程是串行还是并发还是并行
多线程其实也是并发的,串行指的是task1完全执行完毕之后才去执行task2,如下的代码解析。这也是CPython的一大诟病之一,虽然说在I/O密集型的操作中并不会太多的去影响性能,但是相对于多核多线程并发的来说,很显然CPython做的还不是很好。(以目前我的水品来看,觉得如果一个线程内可以有多个python解释器就好了.......哈哈哈)
from threading import Thread, current_thread
什么时候开多线程和多进程
需要有四个任务去处理
方案一:开启四个进程
方案二:开启四个线程
计算密集型性能测试
from multiprocessing import Process
from threading import Thread
import time
I/O密集型性能测试
from threading import Thread
import time
三. 进程池与线程池
进程池和线程池
池就是一个容器,进程池就是用来装进程的容器,那么线程池就是用来装线程池的容器,为什么我们需要进程池和线程池呢?因为在大部分的情况下由于计算机硬件条件的限制我们并不能无线的开启进程或者线程,尽管线程的开销很小,因此我们需要用一个容器来限制能够开启的最大进程数和线程数,从而保证我们的计算机可以正常的提供服务。
进程池的简单使用
from concurrent.futures import ProcessPoolExecutor
import os
import random
import time
def task1(x):
print('%s is running..' % os.getpid())
time.sleep(random.randint(1,3))
if name == 'main':
# 创建一个进程池,进程池的大小可以通过参数进行传递, 如果不指定,默认是cpu的核数
process_pool = ProcessPoolExecutor(4)
# 当执行完submit之后,就会额外的创建出4个进程,用来执行任务
# 函数task1的参数直接在submit中输入就可以传参
process_pool.submit(task1, 1)
time.sleep(30)
在cmd中执行输入命令 【tasklist |findstr pyt】 会发现出现了5个python进程,其中有一个是主线程,另外四个就是进程池内的进程数。
线程池的简单使用
线程池的使用和进程池是一样的,只是导入的名称不一样。
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor from threading import current_thread import os import random import time def task1(x): print('%s is running..' % x) time.sleep(random.randint(1,3)) if __name__ == '__main__': # 创建一个线程池,线程池的大小可以通过参数进行传递, 如果不指定,默认是cpu的核数 * 5 process_pool = ThreadPoolExecutor(4) for i in range(20): # 当第一次执行submit之后,就会额外的创建出4个线程等待着执行任务 # 因此当我们执行了代码之后就会看到一下打印出了四行内容,之后就是执行完一个任务再进行下一个任务,最多的线程数是5个 # 其中有一个线程是主线程 process_pool.submit(task1, i) # time.sleep(2)四.同步vs异步 阻塞vs非阻塞