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. mysql创建账号及管理权限

    mysql创建账号及管理权限 0.mysql版本8.0.15,服务器版本:RHEL 6.5 1.创建用户名密码 mysql> use mysql; mysql> create user ' ...

  2. python使用selector模块编写FTP

    server import os import socket import time import selectors BASE_DIR = os.path.dirname(os.path.abspa ...

  3. MVC3学习:Sql Server2005中时间类型DateTime的显示

    在Sql Server2005中,如果将某字段定义成日期时间类型DateTime,那么在视图中会默认显示成年月日时分秒的方式(如 2013/8/6 13:37:33) 如果只想显示成年月日形式,不要时 ...

  4. 工具-CocoaPods安装和使用及卸载

    CocoaPods是iOS最常用的第三方类库管理工具,绝大部分有名的开源类库都支持CocoaPods. 我们在使用gem更新的时候,经常会为速度抓狂,其实gem默认的源是https://rubygem ...

  5. vue中修改Element ui样式不起作用

    公司做的一个后台系统,由于Elemen ui是响应式的,在小屏笔记本中,一行两列的表单会自动变成一行一列,这样就很不美观了,由于是后台系统,当时也没考虑适配问题. 老总 地表最强的电脑 运行了一下,当 ...

  6. 【Java初探实例篇01】——Java语言基础

    示例系列,将对每节知识辅以实际代码示例,通过代码实际编写,来深入学习和巩固学习的知识点. IDE:intellij IDEA: 语言:Java 本次示例:Java语言基础知识的应用. 创建包day_4 ...

  7. 对html中iframe的研究

    虽然平时不怎么用iframe,但经常在网上听一些前辈说iframe怎样怎样,今天索性对iframe来个大研究,那样就不必去记那些条条框框了,自己体验一遍比看什么都好. 创建两个文件一个index.ht ...

  8. 交换排序:冒泡排序vs快速排序

    在开发的过程中, 经常会遇到集合排序, 那么一般情况下, 我们都是使用list.OrderBy()的方式来排序, 也无需关注到里面算法的实现是个什么样子. 正好这几天准备回顾一下数据结构与算法. 首先 ...

  9. postgresql进程及内存结

    一.进程和内存架构图 postgresql数据库启动时,先启动一个postmaster的主进程,然后fork出一些辅助子进程. 二.主进程postmaster -bash-4.2$ which pos ...

  10. JSONPath解析

    访问我的博客 前言 在工作中,经常会遇到从一串 JSON 中提取一个或多个字段的情况,常用的做法就是将其反序列化为 JSONObject 对象,然后从对象中获取,如果是 JSONArray 就进行迭代 ...