#1、from concurrent import futures可以开启进程池和线程池。concurrent是包,futures是模块,ThreadPoolExecutor是类,submit是方法。
#submit创建和开启子线程:
from concurrent import futures
import time
import random def func(n):
print(n)
time.sleep(random.randint(1,3))#看效果:一开始先执行5个线程,后来谁先执行完就结束,轮到下一个线程执行。 p = futures.ThreadPoolExecutor(5) #线程池里有5个线程。
for i in range(10): #开启10个子线程。
p.submit(func,'hello,world') #submit合并了创建线程对象和start的功能。 #2、result获取返回值,shutdown封装了close和join:
#主线程传参给子线程处理数据,子线程把值返回给主线程。
from concurrent import futures
def func(n):
print(n)
return n + 1 thread_pool = futures.ThreadPoolExecutor(5)
t_lst = []
for i in range(10):
t = thread_pool.submit(func,1) #submit提交任务
t_lst.append(t)
thread_pool.shutdown() #shutdown封装了close()和join(),意思是线程池关闭继续放线程的功能,
# 主线程阻塞在这里,等待子线程全部结束之后才变成非阻塞,下面的代码才能继续执行。
#这样操作的结果就是,先打印出n最后才打印n+1。
for t in t_lst:
print(t.result()) #获取返回值 #3、map创建和开启子线程,后面必须是可迭代的,不可以接收返回值,所以如果func有return返回值,是无法接收的。
from concurrent import futures
def func(i):
print(i) thread_pool = futures.ThreadPoolExecutor(5)
thread_pool.map(func,range(10)) #4、回调函数:add_done_callback(call)
#call的args接收func的返回值
from concurrent import futures
def func(i):
return i*'*' def call(args):
print(args.result()) thread_pool = futures.ThreadPoolExecutor(5)
for i in range(10):
t = thread_pool.submit(func,i)
t.add_done_callback(call)
#5、from concurrent import futures 还可以开启进程,只需要把上面的ThreadPoolExecutor修改为ProcessPoolExecutor,再加上
#if __name__ == '__main__'就可以了,其他代码都不需要修改。
if __name__ == '__main__':
p = futures.ProcessPoolExecutor() #6、进程和线程都不能无限开启,进程数量 = CPU+1 ,线程数量 = CPU*5
协程:

#1、greenlet:在单线程中切换状态的模块
from greenlet import greenlet
def eat():
print('a')
g2.switch()
print('c')
g2.switch() def eat2():
print('b')
g1.switch()
print('d') g1 = greenlet(eat)
g2 = greenlet(eat2)
g1.switch() #2、gevent的底层是greenlet
import gevent
def func():
print(1)
gevent.sleep(1) #如果这里是time.sleep(1)是无法切换的,因为gevent只能识别它内置的IO才会自动切换。
print(3) def func1():
print(2)
gevent.sleep(1)
print(4) g1 = gevent.spawn(func)
g2 = gevent.spawn(func1)
# g1.join()
# g2.join()
gevent.joinall([g1,g2]) #相当于g1.join()和g2.join(),主协程等待子协程的结束而结束。
#
#
#
# #3、第一二句代码必须写在最上面,意思是把IO都打成一个包,这样下面的time.sleep就可以识别了,然后就可以切换了。
#第一二句代码能识别gevent内置当中的IO,以及导入模块当中的IO,导入的模块目前学习到的是:time,socket,urllib,requests。
from gevent import monkey
monkey.patch_all()
import time
import gevent
def func(n):
print(n)
time.sleep(1)
print(3) def func1():
print(2)
time.sleep(1)
print(4) g1 = gevent.spawn(func,1)#创建协程对象,g1 = gevent.spawn(func,1,2,3,x=1),可以是位置实参或关键字实参。
g2 = gevent.spawn(func1)
gevent.joinall([g1,g2])
#
#
#
# #4、协程的本质就是在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率。 #5、协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是协程:
# 协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。 #6、需要强调的是:
#1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)
#2. 单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关) #7、对比操作系统控制线程的切换,用户在单线程内控制协程的切换,
#优点如下:1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
# 2. 单线程内就可以实现并发的效果,最大限度地利用cpu
#缺点如下:1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
# 2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程 #8、server:
from gevent import monkey
monkey.patch_all()
import socket
import gevent def talk(conn):
while True:
ret = conn.recv(1024).decode('utf-8')
print(ret)
conn.send(ret.upper().encode('utf-8'))
conn.close() sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
while True: #每接收一个连接就开启一个协程。
conn,addr = sk.accept()
gevent.spawn(talk,conn) sk.close() #client:
import socket
from threading import Thread def talk():
sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
while True:
sk.send(b'hi')
ret = sk.recv(1024).decode('utf-8')
print(ret)
sk.close() for i in range(500):
Thread(target=talk).start()

IO
#阻塞IO:工作效率低
#非阻塞IO:工作效率高,CPU负担大,不建议使用。
#IO多路复用:在有多个对象需要IO阻塞的时候,能够有效的减少阻塞带来的时间损耗,在一定程度上减少CPU的负担。选择这个比较好。
#异步IO:工作效率高,CPU负担小 #IO多路复用:select:选择
#步骤:1、select监视read_lst里的每个对象,当发现client十个线程请求连接,sk会收到信号,每循环一次增加一个conn,
# 十次就是10个conn,这时read_lst列表里面有一个sk和10个conn,sk是不变的。
# 2、接着client每一次发消息过来,conn收到信号,而select每一次都会选择把10个conn中的一个或者多个放在rl里面,不会放sk,
# 接着就执行else下面的代码。
#server:
import socket
import select
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen() read_lst = [sk]
count = 1
while True:
rl,wl,xl = select.select(read_lst,[],[])#select阻塞,rl读列表,wl写列表,xl修改列表。
print(count,rl)
count += 1
for item in rl:
if item == sk:
conn,addr = item.accept()
print(conn)
read_lst.append(conn)
print(read_lst)
else:
ret = item.recv(1024).decode('utf-8')
if not ret: #如果ret是空的
item.close() #关闭conn
read_lst.remove(item) #列表删除这个conn,避免下次重复被使用
else: #ret不是空的
print(ret)
item.send('recv succeed'.encode('utf-8')) #client:
import socket
from threading import Thread
import time
def talk(args):
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
for i in range(10):
time.sleep(2)
sk.send(('线程%s,第%s次对话'%(args,i)).encode('utf-8'))
ret = sk.recv(1024).decode('utf-8')
print(ret)
sk.close()
for i in range(10):
Thread(target=talk,args=(i,)).start()

 

day53-线程池的更多相关文章

  1. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  2. C#多线程之线程池篇3

    在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...

  3. C#多线程之线程池篇2

    在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...

  4. C#多线程之线程池篇1

    在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...

  5. NGINX引入线程池 性能提升9倍

    1. 引言 正如我们所知,NGINX采用了异步.事件驱动的方法来处理连接.这种处理方式无需(像使用传统架构的服务器一样)为每个请求创建额外的专用进程或者线程,而是在一个工作进程中处理多个连接和请求.为 ...

  6. Java线程池解析

    Java的一大优势是能完成多线程任务,对线程的封装和调度非常好,那么它又是如何实现的呢? jdk的包下和线程相关类的类图. 从上面可以看出Java的线程池主的实现类主要有两个类ThreadPoolEx ...

  7. Android线程管理之ExecutorService线程池

    前言: 上篇学习了线程Thread的使用,今天来学习一下线程池ExecutorService. 线程管理相关文章地址: Android线程管理之Thread使用总结 Android线程管理之Execu ...

  8. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  9. -Android -线程池 批量上传图片 -附php接收代码

    (出处:http://www.cnblogs.com/linguanh/) 目录: 1,前序 2,类特点 3,用法 4,java代码 5,php代码 1,前序 还是源于重构,看着之前为赶时间写着的碎片 ...

  10. C#多线程--线程池(ThreadPool)

    先引入一下线程池的概念: 百度百科:线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行, ...

随机推荐

  1. 当DIV内出现滚动条,fixed实效怎么办?

    sticky    盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位.在所有情况下( ...

  2. JS高级学习笔记(6)- 事件循环

    参考文章:深入理解JS引擎的执行机制        JavaScript 异步.栈.事件循环.任务队列 我的笔记:ES系列之Promise async 和 await Event Loop 前提 js ...

  3. poj_2406 KMP寻找重复子串问题

    B - Power Strings Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u S ...

  4. cf1200 E Compress Words(哈希)

    题意 有n个字符串,记为s1,s2……sn,s2与s1合并,合并的方式为:s1的后缀若与s2的前缀相同,就可以重叠起来,要最长的. 举个例子: “1333”  “33345” → “133345” s ...

  5. BUUCTF-WEB-easy_tornado

    知识点: Python Web 框架:Tornado python中的一个渲染函数:render: 渲染变量到模板中,即可以通过传递不同的参数形成不同的页面. 1. render方法的实质就是生成te ...

  6. settings配置数据库和日志

    数据库的配置: 一.mysql配置 pip下载pymysql,用于mysql和django的连接. 在init.py上配置pymsqy. import pymysql pymysql.install_ ...

  7. LeetCode 687. Longest Univalue Path 最长同值路径 (C++/Java)

    题目: Given a binary tree, find the length of the longest path where each node in the path has the sam ...

  8. JavaScript—封装animte动画函数

    封装Animte 动画函数 虽然可能以后的开发中可能根本不需要自己写,Jquery 给我们封装好了,或者用CSS3的一些属性达到这样的效果可能更简单. 我比较喜欢底层的算法实现,万变不离其中,这个逻辑 ...

  9. 数据处理pandas

    1.缺失值时间戳不为NaN,为NaT, 同样判断都为isna()或notna()方法2.删值\去重 df.dropna() df.drop_duplicates() 3.上下值插值 df.fillna ...

  10. spring容器抽象的具体实现

    1.BeanFactory 接口与 ApplicationContext 接口 (1)spring 提供了两种类型的IOC容器实现.BeanFactory 和 ApplicationContext ( ...