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/回调函数)的更多相关文章

  1. Android笔记(三十四) Android中线程之间的通信(六)Handle中的post()方法详解

    我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码: package cn.lixyz.handlertest; ...

  2. “全栈2019”Java多线程第三十四章:超时自动唤醒被等待的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. python并发编程之线程剩余内容(线程队列,线程池)及协程

    1. 线程的其他方法 import threading import time from threading import Thread,current_thread def f1(n): time. ...

  4. COJ966 WZJ的数据结构(负三十四)

    WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u  ...

  5. NeHe OpenGL教程 第三十四课:地形

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  6. JAVA之旅(三十四)——自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫

    JAVA之旅(三十四)--自定义服务端,URLConnection,正则表达式特点,匹配,切割,替换,获取,网页爬虫 我们接着来说网络编程,TCP 一.自定义服务端 我们直接写一个服务端,让本机去连接 ...

  7. Java进阶(三十四)Integer与int的种种比较你知道多少?

    Java进阶(三十四)Integer与int的种种比较你知道多少? 前言 如果面试官问Integer与int的区别:估计大多数人只会说到两点:Ingeter是int的包装类,注意是一个类:int的初值 ...

  8. Gradle 1.12用户指南翻译——第三十四章. JaCoCo 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  9. SQL注入之Sqli-labs系列第三十四关(基于宽字符逃逸POST注入)和三十五关

    开始挑战第三十四关和第三十五关(Bypass add addslashes) 0x1查看源码 本关是post型的注入漏洞,同样的也是将post过来的内容进行了 ' \ 的处理. if(isset($_ ...

随机推荐

  1. centos 安装nginx笔记

    添加nginx 存储库 yum install epel-release 安装 yum install nginx 启动 systemctl start nginx

  2. (转载)elasticsearch 查询(match和term)

    原文地址:https://www.cnblogs.com/yjf512/p/4897294.html elasticsearch 查询(match和term) es中的查询请求有两种方式,一种是简易版 ...

  3. Java8-用Lambda表达式给List集合排序

    Lambda用到了JDK8自带的一个函数式接口Comparator<T>. 准备一个Apple类 public class Apple { private int weight; priv ...

  4. 全网最详细的Cloudera Hue执行./build/env/bin/supervisor 时出现KeyError: "Couldn't get user id for user hue"的解决办法(图文详解)

    不多说,直接上干货! 问题详情 如下: [root@bigdata-pro01 hue--cdh5.12.1]# ./build/env/bin/supervisor Traceback (most ...

  5. Python学习--12 异常处理、调试

    异常捕获 语法格式: try: pass except xxx as e: pass except xxx as e: pass ... else: pass finally: pass except ...

  6. Prim Algoritm(最小生成树)

    Prim Algorithm.这个算法可以分为下面几个步骤: 将顶点集V分成两个集合A和B,其中集合A表示目前已经在MST中的顶点,而集合B则表示目前不在MST中的顶点. 在B寻找与集合A连通的最短的 ...

  7. 解决使用vue-cli生成项目后项目地址自动添加#号的问题

    vue-router官网https://router.vuejs.org/zh/guide/ vue的路由在默认的hash模式下,url会带有一个#,不美观,而且在微信分享,授权登录等都会有一些坑.所 ...

  8. Spark2.1.0——深入理解事件总线

    Spark2.1.0——深入理解事件总线 概览 Spark程序在运行的过程中,Driver端的很多功能都依赖于事件的传递和处理,而事件总线在这中间发挥着至关重要的纽带作用.事件总线通过异步线程,提高了 ...

  9. 开源方案搭建可离线的精美矢量切片地图服务-5.Mapbox离线项目实现

    项目成果展示(所有项目文件都在阿里云的共享云虚拟主机上,访问地图可以会有点慢,请多多包涵). 01:中国地图:http://test.sharegis.cn/mapbox/html/3china.ht ...

  10. Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23)

    前言 作为一个 Java 程序员,必须知道Java社区最强网络框架-------Netty,且必须看过源码,才能说是了解这个框架,否则都是无稽之谈.今天楼主不会讲什么理论和概念,而是使用debug 的 ...