进程池,线程池使用

大兔子大兔子 提交于 2020-02-04 11:13:32

进程的概念

第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。[3]
进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。

引入进程原因

  1. 为了提高资源利用率和系统处理能力,现阶段计算机系统都是多道程序系统,即多道程序并发执行。
  2. 优化系统资源,方便计算机调度,避免系统运算紊乱。

进程的并行与并发

并行:并行是指两者同时执行,比如赛跑,两个人都在不停的往前跑;(资源够用,比如三个线程,四核CPU)

并发:并行是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A,交替使用,目的是提高效率。

并行简图

在这里插入图片描述
并发(线程)
在这里插入图片描述

二、进程线程

1、进程
程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。需要强调的是:同一个程序执行两次,那也是两个进程。
进程:资源管理单位(容器)。
线程:最小执行单位,管理线程的是进程。

进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据集、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成;数据集则是程序在执行过程中所需要使用的资源;进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。

2、线程
线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。
线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。线程没有自己的系统资源。

3、线程与进程关系
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,控制该进程的地址空间。
进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)CPU分给线程,即真正在CPU上运行的是线程。

一、为什么要引入线程池
Python中已经有了threading模块,为什么还需要线程池呢 ?
当写爬虫时,需要控制同时爬取的线程数,如果创建了20个线程,而同时只允许3个线程在运行,但是20个线程都需要创建和销毁,线程的创建是需要消耗系统资源的,有没有更好的方案呢?
其实只需要三个线程就行了,每个线程各分配一个任务,剩下的任务排队等待,当某个线程完成了任务的时候,排队任务就可以安排给这个线程继续执行。

线程池使用方法

pip install threadpool

pool = ThreadPool(poolsize)  
requests = makeRequests(some_callable, list_of_args, callback)  
[pool.putRequest(req) for req in requests]  
pool.wait()  

第一行定义了一个线程池,表示最多可以创建poolsize这么多线程;

第二行是调用makeRequests创建了要开启多线程的函数,以及函数相关参数和回调函数,其中回调函数可以不写,default是无,也就是说makeRequests只需要2个参数就可以运行;

第三行用法比较奇怪,是将所有要运行多线程的请求扔进线程池,

[pool.putRequest(req) for req in requests]等同于

  for req in requests:  

     pool.putRequest(req) 

第四行是等待所有的线程完成工作后退出。

  • 我的测试样例是 线程池
# _*_ coding:utf-8 _*_


import time
import threadpool
import os

def run(fn):
  #fn: 函数参数是数据列表的一个元素
  time.sleep(2)
  print("进程ID",os.getpid())
  print(fn*fn)


'''
(1)引入threadpool模块

(2)定义线程函数   

(3)创建线程 池threadpool.ThreadPool()   

(4)创建需要线程池处理的任务即threadpool.makeRequests()   

(5)将创建的多个任务put到线程池中,threadpool.putRequest   

(6)等到所有任务处理完毕theadpool.pool()
'''

if __name__ == "__main__":
  testFL = [1,2,3,4,5,6]
  print ('单进程:') #顺序执行(也就是串行执行,单进程)
  s = time.time()
  for fn in testFL:
    run(fn)
  t1 = time.time()
  print ("顺序执行时间:", int(t1 - s))


  print ('多个线程并发:')

  pool = threadpool.ThreadPool(3)

  调用makeRequests创建了要开启多线程的函数
  requests = threadpool.makeRequests(run,testFL)

  # 将所有要运行多线程的请求扔进线程池
  for req in requests:
      pool.putRequest(req)
  pool.wait() #等待所有的线程完成工作后退出

  t2 = time.time()
  print ("并行执行时间:", int(t2-t1))


  • 进程池
# -*- coding: utf-8 -*-
import time
from multiprocessing import Pool
import os

def run(fn):
  #fn: 函数参数是数据列表的一个元素
  time.sleep(2)
  print("进程ID",os.getpid())
  print(fn*fn)

if __name__ == "__main__":
  testFL = [1,2,3,4,5,6]
  print ('单进程:') #顺序执行(也就是串行执行,单进程)
  s = time.time()
  for fn in testFL:
    run(fn)
  t1 = time.time()
  print ("顺序执行时间:", int(t1 - s))

  print ('多个进程,并行执行:') #创建多个进程,并行执行
  pool = Pool(3)  #创建拥有10个进程数量的进程池
  #testFL:要处理的数据列表,run:处理testFL列表中数据的函数
  pool.map(run, testFL)

  pool.close()#关闭进程池,不再接受新的进程
  pool.join()#主进程阻塞等待子进程的退出
  t2 = time.time()
  print ("并行执行时间:", int(t2-t1))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!