concurrent 模块

回顾:

  对于python来说,作为解释型语言,Python的解释器必须做到既安全又高效。我们都知道多线程编程会遇到的问题,解释器要留意的是避免在不同的线程操作内部共享的数据,同时它还要保证在管理用户线程时保证总是有最大化的计算资源。而python是通过使用全局解释器锁来保护数据的安全性:

  python代码的执行由python虚拟机来控制,即Python先把代码(.py文件)编译成字节码(字节码在Python虚拟机程序里对应的是PyCodeObject对象,.pyc文件是字节码在磁盘上的表现形式),交给字节码虚拟机,然后虚拟机一条一条执行字节码指令,从而完成程序的执行。python在设计的时候在虚拟机中,同时只能有一个线程执行。同样地,虽然python解释器中可以运行多个线程,但在任意时刻,只有一个线程在解释器中运行。而对python虚拟机的访问由全局解释器锁来控制,正是这个锁能保证同一时刻只有一个线程在运行

多线程执行方式:

  • 设置GIL(global interpreter lock).
  • 切换到一个线程执行。
  • 运行:
  • a,指定数量的字节码指令。
  • b,线程主动让出控制(可以调用time.sleep(0))。
  • 把线程设置为睡眠状态。
  • 解锁GIL.
  • 再次重复以上步骤。
  GIL的特性,也就导致了python不能充分利用多核cpu。而对面向I/O的(会调用内建操作系统C代码的)程序来说,GIL会在这个I/O调用之前被释放,以允许其他线程在这个线程等待I/O的时候运行。如果线程并为使用很多I/O操作,它会在自己的时间片一直占用处理器和GIL。这也就是所说的:I/O密集型python程序比计算密集型的程序更能充分利用多线程的好处。
总之,不要使用python多线程,使用python多进程进行并发编程,就不会有GIL这种问题存在,并且也能充分利用多核cpu

threading使用回顾:

import threading
import time def run(n):
semaphore.acquire()
time.sleep(2)
print("run the thread: %s" % n)
semaphore.release() if __name__ == '__main__':
start_time = time.time()
thread_list = []
semaphore = threading.BoundedSemaphore(5) # 信号量,最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run, args=(i,))
t.start()
thread_list.append(t)
for t in thread_list:
t.join() used_time = time.time() - start_time
print('用时',used_time) # 用时 8.04102110862732

  

ThreadPoolExecutor多并发:

1、submit

import time
from concurrent import futures def run(n):
time.sleep(2)
print("run the thread: %s" % n) if __name__ == '__main__':
start = time.time()
with futures.ThreadPoolExecutor(5) as executor:
for i in range(20):
executor.submit(run,i) print(time.time()-start) # 8.006775379180908

2、map

import time
from concurrent import futures def run(n):
time.sleep(2)
print("run the thread: %s" % n) if __name__ == '__main__':
start = time.time()
with futures.ThreadPoolExecutor(5) as executor:
executor.map(run,range(20)) print(time.time()-start) # 8.006775379180908 

executor.submit 和 futures.as_completed 这个组合比executor.map 更灵活,因为 submit 方法能处理不同的可调用对象和参数,而 executor.map 只能处理参数不同的同一个可调用对象。此外,传给 futures.as_completed 函数的期物集合可以来自多个 Executor 实例,例如一些由 ThreadPoolExecutor 实例创建,另一些由ProcessPoolExecutor创建

ProcessPoolExecutor多并发:

1、submit

import time
from concurrent import futures import time
from concurrent import futures def run(n):
time.sleep(2)
print("run the thread: %s" % n) if __name__ == '__main__':
start = time.time()
with futures.ProcessPoolExecutor(5) as executor:
for i in range(20):
executor.submit(run, i) print(time.time() - start) # 8.365714311599731

2、map

import time
from concurrent import futures import time
from concurrent import futures def run(n):
time.sleep(2)
print("run the thread: %s" % n) if __name__ == '__main__':
start = time.time()
with futures.ProcessPoolExecutor(5) as executor:
executor.map(run, range(20)) print(time.time() - start) # 8.317736864089966

接口压力测试的脚本

# #!/usr/bin/env python
# # -*- coding:utf-8 -*- import os
import time
import logging
import requests
import threading
from multiprocessing import Lock,Manager
from concurrent import futures download_url = 'http://192.168.188.105:8888'
workers = 250
cpu_count = 4 session = requests.Session() def handle(cost,mutex,contain):
with mutex:
min_cost = contain['min_cost']
max_cost = contain['max_cost']
hit_count = contain['hit_count']
average_cost = contain['average_cost']
if min_cost == 0:
contain['min_cost'] = cost
if min_cost > cost:
contain['min_cost'] = cost
if max_cost < cost:
contain['max_cost'] = cost
average_cost = (average_cost*hit_count + cost) / (hit_count + 1)
hit_count +=1
contain['average_cost'] = average_cost
contain['hit_count'] = hit_count
logging.info(contain) def download_one(mutex,contain):
while True:
try:
stime = time.time()
request = requests.Request(method='GET', url=download_url,)
prep = session.prepare_request(request)
response = session.send(prep, timeout=50)
etime = time.time()
print(response.status_code)
logging.info('process[%s] thread[%s] status[%s] cost[%s]',os.getpid(),threading.current_thread().ident,
response.status_code,etime-stime)
handle(float(etime-stime),mutex,contain)
# time.sleep(1)
except Exception as e:
logging.error(e)
print(e) def new_thread_pool(mutex,contain):
with futures.ThreadPoolExecutor(workers) as executor:
for i in range(workers):
executor.submit(download_one,mutex,contain) def subprocess():
manager = Manager()
mutex = manager.Lock()
contain = manager.dict({'average_cost': 0, 'min_cost': 0, 'max_cost': 0, 'hit_count': 0}) with futures.ProcessPoolExecutor(cpu_count) as executor:
for i in range(cpu_count):
executor.submit(new_thread_pool,mutex,contain) if __name__ == '__main__':
logging.basicConfig(filename="client.log", level=logging.INFO,
format="%(asctime)s [%(filename)s:%(lineno)d] %(message)s", datefmt="%m/%d/%Y %H:%M:%S [%A]")
subprocess()

  

  

Python开发【模块】:Concurrent的更多相关文章

  1. python 全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)

    昨日内容回顾 线程什么是线程?线程是cpu调度的最小单位进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的 一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的在当 ...

  2. python全栈开发,Day42(Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures)

    昨日内容回顾 线程 什么是线程? 线程是cpu调度的最小单位 进程是资源分配的最小单位 进程和线程是什么关系? 线程是在进程中的一个执行单位 多进程 本质上开启的这个进程里就有一个线程 多线程 单纯的 ...

  3. Thread类的其他方法,同步锁,死锁与递归锁,信号量,事件,条件,定时器,队列,Python标准模块--concurrent.futures

    参考博客: https://www.cnblogs.com/xiao987334176/p/9046028.html 线程简述 什么是线程?线程是cpu调度的最小单位进程是资源分配的最小单位 进程和线 ...

  4. Python标准模块--concurrent.futures(进程池,线程池)

    python为我们提供的标准模块concurrent.futures里面有ThreadPoolExecutor(线程池)和ProcessPoolExecutor(进程池)两个模块. 在这个模块里他们俩 ...

  5. Python标准模块--concurrent.futures

    1 模块简介 concurrent.futures模块是在Python3.2中添加的.根据Python的官方文档,concurrent.futures模块提供给开发者一个执行异步调用的高级接口.con ...

  6. Python标准模块--concurrent.futures 进程池线程池终极用法

    concurrent.futures 这个模块是异步调用的机制concurrent.futures 提交任务都是用submitfor + submit 多个任务的提交shutdown 是等效于Pool ...

  7. python开发模块基础:re正则

    一,re模块的用法 #findall #直接返回一个列表 #正常的正则表达式 #但是只会把分组里的显示出来#search #返回一个对象 .group()#match #返回一个对象 .group() ...

  8. python开发模块基础:异常处理&hashlib&logging&configparser

    一,异常处理 # 异常处理代码 try: f = open('file', 'w') except ValueError: print('请输入一个数字') except Exception as e ...

  9. python开发模块基础:os&sys

    一,os模块 os模块是与操作系统交互的一个接口 #!/usr/bin/env python #_*_coding:utf-8_*_ ''' os.walk() 显示目录下所有文件和子目录以元祖的形式 ...

  10. python开发模块基础:序列化模块json,pickle,shelve

    一,为什么要序列化 # 将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化'''比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?现在我们能想到的方法就是存在文 ...

随机推荐

  1. ueditor1_4_3_3编辑器的应用

    教程使用的是ueditor1_4_3_3版本. 首先到官网http://ueditor.baidu.com/website/download.html下载jsp  utf-8版 下载好以后,解压,把解 ...

  2. HBase原理、基本概念、基本架构-3

    HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型.它存储的是 ...

  3. 转:windows 下 netsh 实现 端口映射(端口转发)

    本文转自:本文出自 “httpyuntianjxxll.spac..” 博客,请务必保留此出处http://333234.blog.51cto.com/323234/1135361 -----hapr ...

  4. 有限状态机FSM详解及其实现

    有限状态机,也称为FSM(Finite State Machine),其在任意时刻都处于有限状态集合中的某一状态.当其获得一个输入字符时,将从当前状态转换到另一个状态,或者仍然保持在当前状态.任何一个 ...

  5. Windows "计划任务"功能设置闹钟~

    相信很多人和我一样在使用电脑时都会遇到这样一个麻烦:不知道如何在windows 中设置一个闹铃.当我们在“开始”菜单的所有程序中找了一遍又一遍,甚至使用Everything.exe做全盘的搜索,都没有 ...

  6. Java精选笔记_JSP开发模型

    JSP开发模型 JSP Model JSP Model1简单轻便,适合小型Web项目的快速开发. JSP Model2模型是在JSP Model1的基础上提出的,它提供了更清晰的代码分层,更适用于多人 ...

  7. POJ 1321 棋盘问题(状态压缩DP)

    不总结的话, 同一个地方会 WA 到死 思路: 状态压缩 DP. 1. s 表示压缩状态, 若第 i 列放了棋子, 那么该列置 1, 否则该列置 0. 假如 s = 3(0x011) 那么表示棋盘的第 ...

  8. swift开发之 -- 自动轮播图(UIScrollView+UIPageControl+Timer)

    比较简单,原理就不说了,这里只做记录: 代码如下: 1,准备 var pageControl:UIPageControl? var myscrollView:UIScrollView? var myT ...

  9. 【RF库Collections测试】Get From Dictionary

    Name:Get From DictionarySource:Collections <test library>Arguments:[ dictionary | key ]Returns ...

  10. MySQL 密码设置

    如何修改 MySQL 密码: [root@localhost ~]$ mysqladmin -uroot password 'newPass' # 在无密码的情况下设置密码 [root@localho ...