之前实现的数据共享的方式只有两种结构Value和Array。Python中提供了强大的Manager专门用来做数据共享的,Manager是进程间数据共享的高级接口。 Manager()返回的manager对象控制了一个server进程,此进程包含的python对象可以被其他的进程通过proxies来访问。从而达到多进程间数据通信且安全。Manager支持的类型有list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Queue, Value和Array。

下面看一个用于多进程共享dict和list数据:

from multiprocessing import Manager, Process

def worker(dt, lt):
for i in range(10):
dt[i] = i*i # 访问共享数据 lt += [x for x in range(11, 16)] if __name__ == '__main__':
manager = Manager()
dt = manager.dict()
lt = manager.list()
p = Process(target=worker, args=(dt, lt))
p.start()
p.join(timeout=3)
print(dt)
print(lt)
结果:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
[11, 12, 13, 14, 15]

进程池

当使用Process类管理非常多(几十上百个)的进程时,就会显得比较繁琐,Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程。

import time

import multiprocessing

def fun(msg):
print("#########start#### {0}".format(msg))
time.sleep(3)
print("#########end###### {0}".format(msg)) if __name__ == '__main__':
print("start main")
pool = multiprocessing.Pool(processes=3) #在进程池中创建3个进程
for i in range(1, 7):
msg = "hello {0}".format(i)
pool.apply_async(fun, (msg,))# 执行时间6s+
# pool.apply(fun, (msg,)) #执行时间 6*3=18s+
pool.close() #在调用join之前,要先调用close,否则会报错,close执行完不会有新的进程加入到pool
pool.join() #join 是等待所有的子进程结束,必须在close之后调用
print("end main") 结果:
start main
start hello 1
start hello 2
start hello 3
end hello 1
start hello 4
end hello 2
start hello 5
end hello 3
start hello 6
end hello 4
end hello 5
end hello 6
end main
6.18000006676 # 使用pool.apply_async()所花费时间
18.2129998207 # 使用pool.apply()所花费时间

pool.apply_async   非阻塞,定义的进程池最大数的同时执行

pool.apply         一个进程结束,释放回进程池,开始下一个进程

从上面的结果中我们可以看到,使用pool.apply_async所花费的时间较少。

多线程

Python中提供了threading模块来对多线程进行操作,线程是应用程序中工作的最小单元,多线程适用于密集型io。

多线程的实现方式有两种:
方法一:将要执行的方法作为参数传给Thread的构造方法(和多进程类似)
t = threading.Thread(target=action, args=(i,))

方法二:从Thread类继承,并重写run()方法。

方法一示例:

import threading

def worker(args):
print("开始子进程 {0}".format(args))
print("结束子进程 {0}".format(args)) if __name__ == '__main__': print("start main")
t1 = threading.Thread(target=worker, args=(1,)) # 和多进程类似
t2 = threading.Thread(target=worker, args=(2,))
t1.start()
t2.start()
print("end main") 结果:
start main
开始子进程 1
结束子进程 1
开始子进程 2
end main
结束子进程 2

方法二示例:

import threading

import time

class Hello(threading.Thread):
# 对run()方法进行重写
def __init__(self, args):
super(Hello, self).__init__()
self.args = args def run(self):
print("开始子进程 {0}".format(self.args))
time.sleep(1)
print("结束子进程 {0}".format(self.args)) if __name__ == '__main__': a = 1
print("start main")
t1 = Hello(1)
t2 = Hello(2)
t1.start()
t2.start()
print("end main") 结果:
start main
开始子进程 1
开始子进程 2
end main
结束子进程 2
结束子进程 1

线程锁

当多线程争夺锁时,允许第一个获得锁的线程进入临街区,并执行代码。所有之后到达的线程将被阻塞,直到第一个线程执行结束,退出临街区,并释放锁。
需要注意,那些阻塞的线程是没有顺序的。

import time
import threading def sub():
global count
lock.acquire() #上锁,第一个线程如果申请到锁,会在执行公共数据的过程中持续阻塞后续线程
#即后续第二个或其他线程依次来了发现已经被上锁,只能等待第一个线程释放锁
#当第一个线程将锁释放,后续的线程会进行争抢 '''线程的公共数据'''
temp=count
print("temp is {0}".format(temp))
time.sleep(0.001)
count=temp+1
print("count is {0}".format(count))
'''线程的公共数据''' lock.release() # 释放锁
time.sleep(2)
count=0 l=[]
lock=threading.Lock()
for i in range(100):
t=threading.Thread(target=sub,args=())
t.start()
l.append(t)
for t in l:
t.join()
print(count) 结果:
100

线程池

采用线程池,花费的时间更少。

语法结构示例:

import threadpool
def ThreadFun(arg1,arg2):
pass
def main():
device_list=[object1,object2,object3......,objectn]#需要处理的设备个数
task_pool=threadpool.ThreadPool(8)#8是线程池中线程的个数
request_list=[]#存放任务列表
#首先构造任务列表
for device in device_list:
request_list.append(threadpool.makeRequests(ThreadFun,[((device, ), {})]))
#将每个任务放到线程池中,等待线程池中线程各自读取任务,然后进行处理,使用了map函数,不了解的可以去了解一下。
map(task_pool.putRequest,request_list)
#等待所有任务处理完成,则返回,如果没有处理完,则一直阻塞
task_pool.poll()
if __name__=="__main__":
main()

pip install threadpool   # 安装threadpool
from threadpool import *   #导入模块
pool = ThreadPool(size) # 定义一个线程池,最多能创建size个线程
requests = makeRequests() # 调用makeRequests创建了要开启多线程的函数,以及函数相关参数和回调函数,其中回调函数可以不写,default是无,也就是说makeRequests只需要2个参数就可以运行;
[pool.putRequest(req) for req in requests] # 将所有要运行多线程的请求扔进线程池
pool.wait() # 等待所有的线程完成工作后退出。

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

例子:

import threadpool

def hello(m, n, o):
print("m = {0} n={1} o={2}".format(m, n, o)) if __name__ == '__main__':
# 方法1
lst_vars_1 = ['', '', ''] # 需要处理的线程个数
lst_vars_2 = ['', '', '']
func_var = [(lst_vars_1, None), (lst_vars_2, None)]
# 方法2
# dict_vars_1 = {'m': '1', 'n': '2', 'o': '3'}
# dict_vars_2 = {'m': '4', 'n': '5', 'o': '6'}
# func_var = [(None, dict_vars_1), (None, dict_vars_2)] pool = threadpool.ThreadPool(2) # 线程池中的线程个数
requests = threadpool.makeRequests(hello, func_var) # 创建了要开启多线程的函数,创建需要线程池处理的任务,只需要两个参数
[pool.putRequest(req) for req in requests] # 将每个任务放入到线程池中
pool.wait() 结果:
m = 1 n=2 o=3
m = 4 n=5 o=6

python多进程(二)的更多相关文章

  1. 【Python从入门到精通】(二十五)Python多进程的使用

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本篇重点介绍Python多进程的使用,读者朋友们可以将多进程和多线程两者做一个对比学习. 干货满满,建议收藏,需要用到时常看看. 小伙伴们如有问题 ...

  2. Python多进程(1)——subprocess与Popen()

    Python多进程方面涉及的模块主要包括: subprocess:可以在当前程序中执行其他程序或命令: mmap:提供一种基于内存的进程间通信机制: multiprocessing:提供支持多处理器技 ...

  3. Python 多进程multiprocessing

    一.python多线程其实在底层来说只是单线程,因此python多线程也称为假线程,之所以用多线程的意义是因为线程不停的切换这样比串行还是要快很多.python多线程中只要涉及到io或者sleep就会 ...

  4. Python 多进程 多线程 协程 I/O多路复用

    引言 在学习Python多进程.多线程之前,先脑补一下如下场景: 说有这么一道题:小红烧水需要10分钟,拖地需要5分钟,洗菜需要5分钟,如果一样一样去干,就是简单的加法,全部做完,需要20分钟:但是, ...

  5. 【转】【Python】Python多进程与多线程

    1.1 multiprocessing multiprocessing是多进程模块,多进程提供了任务并发性,能充分利用多核处理器.避免了GIL(全局解释锁)对资源的影响. 有以下常用类: 类 描述 P ...

  6. python多进程详解

    目录 python多进程 序.multiprocessing 一.Process process介绍 例1.1:创建函数并将其作为单个进程 例1.2:创建函数并将其作为多个进程 例1.3:将进程定义为 ...

  7. 一篇文章搞定Python多进程(全)

    1.Python多进程模块 Python中的多进程是通过multiprocessing包来实现的,和多线程的threading.Thread差不多,它可以利用multiprocessing.Proce ...

  8. python多进程multiprocessing Pool相关问题

    python多进程想必大部分人都用到过,可以充分利用多核CPU让代码效率更高效. 我们看看multiprocessing.pool.Pool.map的官方用法 map(func, iterable[, ...

  9. python 多进程数量 对爬虫程序的影响

    1. 首先看一下 python 多进程的优点和缺点 多进程优点: 1.稳定性好: 多进程的优点是稳定性好,一个子进程崩溃了,不会影响主进程以及其余进程.基于这个特性,常常会用多进程来实现守护服务器的功 ...

  10. Python多进程编程

    转自:Python多进程编程 阅读目录 1. Process 2. Lock 3. Semaphore 4. Event 5. Queue 6. Pipe 7. Pool 序. multiproces ...

随机推荐

  1. 概述Java集合框架

    JAVA集合框架主要分为三个部分:接口,实现和算法.接口是指以Collection和Map为起始的一系列公用接口,其中还有Vector接口,也就是迭代器,Collection接口下面又有List 和S ...

  2. 修改request请求参数

    本质上来讲,request请求当中的参数是无法更改的,也不能添加或者删除: 但在后台程序中,一般对request的参数的操作,都是通过request的getParameter.getParameter ...

  3. IDEA 中edit configurations加号找不到tomcat server

    前言:在本机 idea 中搭建 springMVC 项目,正准备配置 Tomcat 时,发现没有 tomcat server 选项,而我的 idea 是有这个插件的,所以解决问题的方案应该是另一个地方 ...

  4. NOIP2017 题解

    QAQ--由于没报上名并没能亲自去,自己切一切题聊以慰藉吧-- 可能等到省选的时候我就没有能力再不看题解自己切省选题了--辣鸡HZ毁我青春 D1T1 小凯的疑惑 地球人都会做,懒得写题解了-- D1T ...

  5. BZOJ4566: [Haoi2016]找相同字符(后缀自动机)

    题意 题目链接 Sol 直接在SAM上乱搞 枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值 然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树 ...

  6. L1 Cache, L2 Cache读取命中率与时钟周期计算

    CPU在Cache中找到有用的数据被称为命中,当Cache中没有CPU所需的数据时(这时称为未命中),CPU才访问内存.从理论上讲,在一颗拥有2级Cache的CPU中,读取L1 Cache的命中率为8 ...

  7. 实现ListView的加载更多的效果,如何将按钮布局到始终在ListView的最后一行

    实现方式一:在代码中实现: 1,在一个布局中定义一个Button,在活动中加载Button的父布局, 例如:View bottomView = getLayoutInflater().inflate( ...

  8. 如何利用API导出带有页眉页脚的excel

     在报表中设置的页眉页脚在页面中是看不到的,如下图: 页面中的效果: 在打印的时候,可以看到页眉页脚的效果: 那么,如果将页眉页脚导入到导出的excel中呢.我们可以通过API来进行设置: < ...

  9. java boolean 值在内存中占几位?

      java boolean 值在内存中占几位?    <Java虚拟机规范>中这样描述:虽然定义了boolean这种数据类型,但是只对它提供了非常有限的支持.在Java虚拟机中没有任何供 ...

  10. Pig是轻类型的

    总体来说Pig是“强类型”的,但Pig又允许用户不指定输入数据的类型,而可以自己根据用户的使用方式进行推测. 称Pig是“轻类型”的更合适,它确实对类型有严格的要求,但是如果没有明确定义类型也是可以处 ...