一:进程池与线程池(同步,异步+回调函数)
先造个池子,然后放任务
为什么要用“池”:池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务
池子内什么时候装进程:并发的任务属于计算密集型
池子内什么时候装线程:并发的任务属于IO密集型
#提交任务的两种方式:
    # 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的
    # 异步调用:提交完一个任务之后,不在原地等待,结果???,而是直接执行下一行代码,会导致任务是并发执行的
 
p=ProcessPoolExecutor(4) 
obj=p.submit(函数名,参1,参2)
obj.add_done_callback(函数名2)
#后续回调是obj会将自身传给函数名2,所以函数名2必须有且仅有一个参数。(多进程,回调主进程干)(多线程回调,子线程们干除开主线程)
p.shutdown(wait=True)#(等同于p.close()(不允许向池中放新任务) + p.join())关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
obj.result()
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time,random,os
def task(name,n):
    print('%s%s is running' %(name,os.getpid()))
    time.sleep(random.randint(1,3))
    return n**2
if __name__ == '__main__':
    # print(os.cpu_count())
    p=ProcessPoolExecutor(4)
    #提交任务的两种方式:
    # 同步调用:提交完一个任务之后,就在原地等待,等待任务完完整整地运行完毕拿到结果后,再执行下一行代码,会导致任务是串行执行的
    # 异步调用:提交完一个任务之后,不在原地等待,结果???,而是直接执行下一行代码,会导致任务是并发执行的
    l=[]
    for i in range(10):
        # 同步提交
        # res=p.submit(task,'进程pid: ',i).result()
        # print(res)
        # 异步提交
        future=p.submit(task,'进程pid: ',i)
        l.append(future)
    p.shutdown(wait=True) #关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
    for future in l:
        print(future.result())
    print('主')
'''
二、协程
1、协程是单线程实现并发
    注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)
    在单线程下(i/o密集型任务)实现多个任务间遇到IO就切换就可以降低单线程的IO时间,从而最大限度地提升单线程的效率
  在单线程下(计算密集型任务)切反而降低效率。
2、实现并发的三种手段:
a单线程下的并发;由程序自己控制,相对速度快
b多线程下的并发;由操作系统控制,相对速度较慢
c多进程下的并发;由操作系统控制,相对速度慢
3、基于yield保存状态,实现两个任务直接来回切换,即并发的效果 (但yield不会遇到阻塞自动切程序)
   PS:如果每个任务中都加上打印,那么明显地看到两个任务的打印是你一次我一次,即并发执行的.
import time
def consumer():
    '''任务1:接收数据,处理数据'''
    while True:
        x=yield
def producer():
    '''任务2:生产数据'''
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)
start=time.time()
producer() #1.0202116966247559
stop=time.time()
print(stop-start)
# 纯计算的任务并发执行
import time
def task1():
    res=1
    for i in range(1000000):
        res+=i
        yield
        time.sleep(10000)  #yield不会自动跳过阻塞
        print('task1')
def task2():
    g=task1()
    res=1
    for i in range(1000000):
        res*=i
        next(g)
        print('task2')
start=time.time()
task2()
stop=time.time()
print(stop-start)
4、单线程下实现遇到IO切换
 1、用greenlet(封装yield,遇到IO不自动切)
 from greenlet import greenlet
 import time
 def eat(name):
  print('%s eat 1' %name)
  time.sleep(30)
  g2.switch('alex')  #只在第一次切换时传值
  print('%s eat 2' %name)
  g2.switch()
 def play(name):
  print('%s play 1' %name)
  g1.switch()
  print('%s play 2' %name)
 g1=greenlet(eat)
 g2=greenlet(play)
 g1.switch('egon')
 2、用gevent模块(封装greenlet,不处理的话,遇到自己的IO才主动切)
 import gevent
 def eat(name):
  print('%s eat 1' %name)
  gevent.sleep(5)  #换成time.sleep(5),不会自动切
  print('%s eat 2' %name)
 def play(name):
  print('%s play 1' %name)
  gevent.sleep(3)
  print('%s play 2' %name)
 g1=gevent.spawn(eat,'egon')
 g2=gevent.spawn(play,'alex')
 # gevent.sleep(100)
 # g1.join()
 # g2.join()
 gevent.joinall([g1,g2])
5、用gevent模块(封装greenlet,处理的话,遇到其他IO也主动切)
from gevent import monkey;monkey.patch_all()
from threading import current_thread
from gevent import spawn,joinall #pip3 install gevent
import time
def play(name):
    print('%s play 1' %name)
    time.sleep(5)
    print('%s play 2' %name)
def eat(name):
    print('%s eat 1' %name)
    time.sleep(3)
    print('%s eat 2' %name)

g1=spawn(play,'刘清正')
g2=spawn(eat,'刘清正')

# g1.join()
# g2.join()
joinall([g1,g2])

(并发编程)进程池线程池--提交任务2种方式+(异步回调)、协程--yield关键字 greenlet ,gevent模块的更多相关文章

  1. Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析

    目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...

  2. 【Java并发编程六】线程池

    一.概述 在执行并发任务时,我们可以把任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程,只要池里有空闲的线程,任务就会分配一个线程执行.在线程池的内部,任务被插入一个阻塞队列(Blo ...

  3. day33_8_15 并发编程4,线程池与协程,io模型

    一.线程池 线程池是一个处理线程任务的集合,他是可以接受一定量的线程任务,并创建线程,处理该任务,处理结束后不会立刻关闭池子,会继续等待提交的任务,也就是他们的进程/线程号不会改变. 当线程池中的任务 ...

  4. 并发编程 --进、线程池、协程、IO模型

    内容目录: 1.socket服务端实现并发 2.进程池,线程池 3.协程 4.IO模型 1.socket服务端实现并发 # 客户端: import socket client = socket.soc ...

  5. Java并发编程:Java线程池

    转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题 ...

  6. 潭州课堂25班:Ph201805201 并发(进程与线程池) 第十四课 (课堂笔记)

    循环执行一个线程 # -*- coding: utf-8 -*- # 斌彬电脑 # @Time : 2018/7/20 0020 5:35 import threading import queue ...

  7. 并发编程-concurrent指南-线程池ExecutorService的实例

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  8. Java并发编程 (九) 线程调度-线程池

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 声明:实际上,在开发中并不会普遍的使用Thread,因为它具有一些弊端,对并发性能的影响比较大,如下: ...

  9. CSIC_716_20191207【并发编程---进程与线程】

    僵尸进程与孤儿进程 ........... 守护进程 from Multiprocessing  import Process 在 suboprocess.start( ) 的上一行,增加 subpr ...

随机推荐

  1. vue watch bug记录

    watch中,写箭头函数,获取不到正确的this 换成function,正确取到this

  2. Date类、SimpleDateFormat类

    Date 构造方法: 1.无参数构造方法: Date date = new Date(); System.out.println(date);// Thu Mar 28 16:28:40 CST 20 ...

  3. Node.js学习入门

    Node.js是什么 Node.js是一个可以允许我们在服务器端运行JavaScript代码的程序. 这是什么意思呢?通常,我们写的JavaScript代码都是在浏览器中运行的. 实际上,浏览器就是一 ...

  4. SpringBoot系列: 使用 flyway 管理数据库版本

      Flyway 和 Liquibase 都是 Java 项目中常用的 DB migration 工具, 从使用简便性看,Flyway 比 Liquibase 更简单, 从 github 的 star ...

  5. MVC |分部视图 PartialView()

    介绍如何定义 其实它和普通视图没有多大区别,只是创建分部视图的时候视图里没有任何内容,你需要什么标签你自己加.第二就是分部视图不会执行_ViewStart.cshtml中的内容) 控制器 Partia ...

  6. JavaScript 小工具

    1. 字符串格式化输出 支持形如: Orders of {1} or more {0}' {0},{1}代表第几个参数,包含了完善的异常处理.当给定参数少于格式化串中占位符个数时,未找到的直接留白. ...

  7. mui列表系列

    详细操作见代码: <!doctype html> <html> <head> <meta charset="UTF-8"> < ...

  8. linux 查看文件夹大小

    参考链接:  http://www.cnblogs.com/iconfig/p/4863063.html

  9. Linux故障:linux中使用ifconfig命令查看网卡信息时显示为eth1,但是在network-scripts中只有ifcfg-eth0的配置文件,并且里面的NAME="eth0"。

    linux中使用ifconfig命令查看网卡信息时显示为eth1,但是在network-scripts中只有ifcfg-eth0的配置文件,并且里面的NAME="eth0".   ...

  10. 给tomcat 配置https

    参考以下链接 https://www.cnblogs.com/xiaoliao/p/5778262.html 本人使用环境和版本 tomcat 7.7 阿里云 centos 7还是red hat 浏览 ...