第三十四天- 线程队列、线程池(map/submit/shutdown/回调函数)
1.线程列队
queue队列 :使用import queue,用法与进程Queue一样
class queue.Queue(maxsize=0)
# 先进先出:
q = queue.Queue(3) # 也可以不加数字表示不限
q.put('约吗')
q.put('你个糟老头')
q.put('约个鬼!')
# q.put_nowait() # 没有数据会报错 可以try解决
print(q.get())
print(q.get())
print(q.get())
q.get_nowait()
先进先出
class queue.LifoQueue(maxsize=0)
import queue # 后进先出:
q = queue.LifoQueue(4)
q.put('first')
q.put('second')
q.put('third')
q.put_nowait(1)
print(q.get())
print(q.get())
print(q.get())
print(q.get_nowait())
后进先出
class queue.PriorityQueue(maxsize=0)
# 设置优先
q = queue.PriorityQueue(6) # put进入元组,元组第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put((3,'a'))
q.put((2,'b'))
q.put((-3,'c')) # 优先级相同的两个数据,比较第二个元素ASCII码大小,若第二元素为字符串且第一个字符相同则比较第二个
q.put((20,'ww'))
q.put((20,'ws'))
# q.put(20,{'ws',22}) # 不能是字典
# q.put((20,('w',1))) # 后面的值必须是相同数据类型才能比较,可以是元祖,ascii码顺序排序 print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
# print(q.get())
这三种队列都是线程安全的,不会出现多个线程抢占同一个资源或数据的情况。
2.线程池
线程池:早期的时候没有线程池,现在python提供了一个新的内置模块 concurrent.futures,模块里面提供了新的线程池和进程池,之前的进程池是在multiprocessing里面,现在这个在这个新的模块里面,他俩用法上是一样的。为了统一使用方式将进程池和线程池放到一起,使用threadPollExecutor和ProcessPollExecutor的方式一样,且只要通过concurrent.futures导入就可用他们两个
基本方法:
#2 基本方法
#submit(fn, *args, **kwargs)
异步提交任务 #map(func, *iterables, timeout=None, chunksize=1)
取代for循环submit的操作 #shutdown(wait=True)
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前 #result(timeout=None)
取得结果 #add_done_callback(fn)
回调函数
import time
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor def func(n):
time.sleep(0.5)
return n*n if __name__ == '__main__':
t_pool = ThreadPoolExecutor(max_workers=4)
# t_pool = ProcessPoolExecutor(max_workers=4) # 用concurrent.futures可直接转换成进程
t_list = []
for i in range(10):
res = t_pool.submit(func,i) # submit异步提交任务
# print(res.result()) # 等待res的执行结果,拿到了就运行,拿不到就阻塞,放这会变成串行
t_list.append(res) t_pool.shutdown() # 相当于进程池的pool.close() pool.join() print('主线程结束') for res1 in t_list:
print(res1.result())
线程池代码示例
import time
from concurrent.futures import ThreadPoolExecutor def func(n):
time.sleep(1)
return n*n if __name__ == '__main__': t_pool = ThreadPoolExecutor(6)
res = t_pool.map(func,range(10)) # map 取代for循环submit的操作
t_pool.shutdown() print('主线程执行结束')
for i in res:
print(i) # map包含了for循环和submit操作
map方法
import time
from concurrent.futures import ThreadPoolExecutor def func1(n):
time.sleep(1)
return n*n def callback(s):
# print(s)
ss = s.result()+1
print(ss) if __name__ == '__main__':
t_pool = ThreadPoolExecutor(4)
for i in range(10):
t_pool.submit(func1,i).add_done_callback(callback) # 注意map函数没有callback,不能如下使用
# res = t_pool.map(func1,range(10))
# for i in res:
# i.add_done_callback(callback)
回调函数
需注意:注意map函数没有callback
3.GIL锁
背景:
一些语言(java、c++、c)是支持同一个进程中的多个线程是可以应用多核CPU的,也就是我们会听到的现在4核8核这种多核CPU技术的牛逼之处。那么我们之前说过应用多进程的时候如果有共享数据是不是会出现数据不安全的问题啊,就是多个进程同时一个文件中去抢这个数据,大家都把这个数据改了,但是还没来得及去更新到原来的文件中,就被其他进程也计算了,导致数据不安全的问题啊,所以我们是不是通过加锁可以解决啊,多线程大家想一下是不是一样的,并发执行就是有这个问题。但是python最早期的时候对于多线程也加锁,但是python比较极端的(在当时电脑cpu确实只有1核)加了一个GIL全局解释锁,是解释器级别的,锁的是整个线程,而不是线程里面的某些数据操作,每次只能有一个线程使用cpu,也就说多线程用不了多核,但是他不是python语言的问题,是CPython解释器的特性,如果用Jpython解释器是没有这个问题的,Cpython是默认的,因为速度快,Jpython是java开发的,在Cpython里面就是没办法用多核,这是python的弊病,历史问题,虽然众多python团队的大神在致力于改变这个情况,但是暂没有解决。(这和解释型语言(python,php)和编译型语言有关系吗???待定!,编译型语言一般在编译的过程中就帮你分配好了,解释型要边解释边执行,所以为了防止出现数据不安全的情况加上了这个锁,这是所有解释型语言的弊端??)
如图:
但是有了这个锁我们就不能并发了吗?当我们的程序是偏计算的,也就是cpu占用率很高的程序(cpu一直在计算),就不行了,但是如果你的程序是I/O型的(一般你的程序都是这个)(input、访问网址网络延迟、打开/关闭文件读写),在什么情况下用的到高并发呢(金融计算会用到,人工智能(阿尔法狗),但是一般的业务场景用不到,爬网页,多用户网站、聊天软件、处理文件),I/O型的操作很少占用CPU,那么多线程还是可以并发的,因为cpu只是快速的调度线程,而线程里面并没有什么计算,就像一堆的网络请求,我cpu非常快速的一个一个的将你的多线程调度出去,你的线程就去执行I/O操作了
GIL锁与Lock:
GIL保护的是解释器级的数据,保护用户自己的数据则需要自己加锁处理,如下图
第三十四天- 线程队列、线程池(map/submit/shutdown/回调函数)的更多相关文章
- Android笔记(三十四) Android中线程之间的通信(六)Handle中的post()方法详解
我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码: package cn.lixyz.handlertest; ...
- “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- python并发编程之线程剩余内容(线程队列,线程池)及协程
1. 线程的其他方法 import threading import time from threading import Thread,current_thread def f1(n): time. ...
- COJ966 WZJ的数据结构(负三十四)
WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u ...
- NeHe OpenGL教程 第三十四课:地形
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫
JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...
- Java进阶(三十四)Integer与int的种种比较你知道多少?
Java进阶(三十四)Integer与int的种种比较你知道多少? 前言 如果面试官问Integer与int的区别:估计大多数人只会说到两点:Ingeter是int的包装类,注意是一个类:int的初值 ...
- Gradle 1.12用户指南翻译——第三十四章. JaCoCo 插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SQL注入之Sqli-labs系列第三十四关(基于宽字符逃逸POST注入)和三十五关
开始挑战第三十四关和第三十五关(Bypass add addslashes) 0x1查看源码 本关是post型的注入漏洞,同样的也是将post过来的内容进行了 ' \ 的处理. if(isset($_ ...
随机推荐
- Shell - 简明Shell入门04 - 判断语句(If)
示例脚本及注释 #!/bin/bash var=$1 # 将脚本的第一个参数赋值给变量var if test $var # test - check file types and compare va ...
- flask中邮件发送方法
from flask import Flask from flask_mail import Mail, Message app = Flask(__name__) #配置邮件:服务器/端口/传输层安 ...
- 创建python3虚拟环境指令和冻结所安装的包
mkvirtualenv file_name -p python3 去掉后面的 P 和python3 代表创建python2环境 其中p代表路径的意思 冻结所安装包命令 pip freeze > ...
- Flask-Restful详解
Restful API规范 restful api是用于在前端与后台进行通信的一套规范.使用这个规范可以让前后端开发变得更加轻松.以下将讨论这套规范的一些设计细节. 协议: 采用http或者https ...
- C# 添加修改防火墙端口及程序
文章转自:http://sdfiyon.iteye.com/blog/1197511 一.添加 COM 引用 在引用里,选择 COM 页, 找到 NetFwTypeLib , 确定即可 二.添加允许通 ...
- 10分钟打造强大的gvim
感谢Ruchee的共享精神,让我等vim新手省去了配置vim的麻烦(教程地址:配置文件使用指南). 只需要简单的6个步骤,就可以配置完成一个强大的gvim神器,下图是我的最终配置效果图. (另外,我的 ...
- 磁盘分区(20G升50G)
不多说,直接上干货! 本博文的主要内容有 .磁盘分区的概述 .常用的磁盘管理工具 ./下分5G,给/home扩容 .系统自带的fdisk和parted这两款工具 .磁盘空间管理 前言 ...
- 全网最全的Windows下Anaconda2 / Anaconda3里Python语言实现定时发送微信消息给好友或群里(图文详解)
不多说,直接上干货! 缘由: (1)最近看到情侣零点送祝福,感觉还是很浪漫的事情,相信有很多人熬夜为了给爱的人送上零点祝福,但是有时等着等着就睡着了或者时间并不是卡的那么准就有点强迫症了,这是也许程序 ...
- 全网最详细的U盘被损坏导致一般性的软件无法修复的解决办法(必须可以)(图文详解)
不多说,直接上干货! 问题详情 一般,在不正当地操作U盘时,容易出现如下的情况: 解决办法: 本人,在尝试多款U盘修复工具软件后,发现: 成功几率很大,博文本人亲自尝试,并强烈推荐. 欢迎大家,加入我 ...
- 在Idea2017.1中编译时发生如下的错误
错误 在Idea2017.1中编译时发生如下的错误 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8 Information:java: Errors ...