线程queue、事件event及协程

线程queue、事件event及协程

线程queue

多线程抢占资源,让其保持串行的两种方式:

​ 1、互斥锁

​ 2、队列

线程队列分为以下三种:

1、Queue(先进先出)

import queueq = queue.Queue(3)
q.put(1)
q.put(2)
q.put(3)
# q.put(4,block=False)  # 若不设置block参数,默认为True,大于队列长度进入阻塞状态,若设置block为False,大于对列长度直接报错
print(q.get())
print(q.get())
print(q.get())
# print(q.get(timeout=2)) 阻塞2s 还没有值直接报错
# 结果
1
2
3

2、LifoQueue(后进先出)

import queueq = queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
# 结果:
3
2
1

3、PriorityQueue(优先级队列)

import queueq = queue.PriorityQueue(3)
q.put((-1,'awe'))   # 操作对象为元祖,第一个位置的数字越小,优先级越高
q.put((2,6))
q.put((0,3))
print(q.get())
print(q.get())
print(q.get())
# 结果:
(-1, 'awe')
(0, 3)
(2, 6)

事件event

开启两个线程,一个线程运行到中间的某个阶段,触发另个线程执行.两个线程增加了耦合性.

引入事件event的两个阶段:

版本1:(判断全局变量状态)

from threading import Thread
from threading import current_thread
import timeflag =False
def check():print(f'{current_thread().name}监测服务器是否开启')time.sleep(3)global flagflag = Trueprint('服务器已开启')def connect():while not flag:print(f'{current_thread().name}等待连接')time.sleep(0.5)else:print(f'{current_thread().name} 连接成功...')t1 = Thread(target=check,)
t2 = Thread(target=connect,)
t1.start()
t2.start()
# 结果:
Thread-1监测服务器是否开启
Thread-2等待连接
Thread-2等待连接
Thread-2等待连接
Thread-2等待连接
Thread-2等待连接
Thread-2等待连接
服务器已开启
Thread-2 连接成功...

版本2:(事件Event)

from threading import Thread
from threading import current_thread
from threading import Event
import timeevent = Event() # 创建事件对象def check():print(f'{current_thread().name}监测服务器是否开启')time.sleep(3)print(event.is_set()) # 判断事件是否设置event.set() # 设置事件print(event.is_set())print('服务器已开启')def connect():print(f'{current_thread().name}等待连接')event.wait() # 等待事件设置,阻塞状态print(f'{current_thread().name} 连接成功...')t1 = Thread(target=check,)
t2 = Thread(target=connect,)
t1.start()
t2.start()

小练习:

将上述例子改为一个线程监测服务器状态,另一个线程判断服务器状态,如果服务器状态开启,则显示连接成功,此线程每1秒尝试连接服务器一次,一共连接3次,还没连接成功,则显示连接失败

from threading import Thread
from threading import current_thread
from threading import Event
import timeevent = Event() # 创建事件对象def check():print(f'{current_thread().name}监测服务器是否开启')time.sleep(3)event.set() # 设置事件print('服务器已开启')def connect():count = 1while 1:print(f'{current_thread().name}等待连接')event.wait(1) # 等待事件设置,阻塞状态if count == 4:print(f'{current_thread().name}连接成功')count += 1print(f'{current_thread().name}尝试连接{count}次...')else:print(f'{current_thread().name}连接成功')t1 = Thread(target=check,)
t2 = Thread(target=connect,)
t1.start()
t2.start()

协程

协程:简单的来说就是一个线程并发的处理任务.

串行:一个线程执行一个任务,执行完毕之后,执行下一个任务.

并行: 多个cpu执行多个任务, 4个cpu 执行4个任务.

并发: 一个cpu执行多个任务,看起来像是同时运行.

并发真正的核心:切换并且保持状态.

多线程的并发: 3个线程处理10个任务,如果线程1处理的这个任务,遇到阻塞,cpu被操作系统切换到另一个线程,

1729998-20190827182042869-743212080.png

一个线程并发处理任务:以一个线程执行3个任务为例:

1729998-20190827182052237-1055054862.png

协程定义:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

单个cpu并发执行10个任务的三种方式:

​ 1、方式一:开启多进程并发执行, 操作系统切换+保持状态.

​ 2、方式二:开启多线程并发执行,操作系统切换+保持状态.

​ 3、方式三:开启协程并发的执行, 自己的程序 把控着cpu 在3个任务之间来回切换+保持状态.

以上三种实现方式,协程最好,这是因为:

​ 1.协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级

​ 2.协程的运行速度更快

​ 3.协程会长期霸占cpu只执行我程序里面的所有任务.

协程的特点:

  1. 必须在只有一个单线程里实现并发
  2. 修改共享数据不需加锁
  3. 用户程序里自己保存多个控制流的上下文栈(保持状态)
  4. 附加:一个协程遇到IO操作自动切换到其它协程

Greenlet

Greenlet是python中的一个第三方模块,真正的协程模块就是使用greenlet完成的切换

并发的两个核心:切换并且保持状态.接下来我们从一个例子慢慢引入此模块的用法

# 版本一:单切换
def func1():print('in func1')def func2():print('in func2')func1()print('end')func2()# 版本二:切换+保持状态
import time
def gen():while 1:yield 1time.sleep(0.5)  # 手动设置IO,遇到IO无法自动切换def func():obj = gen()for i in range(10):next(obj)
func()# 版本三:切换+保持状态,遇到IO自动切换
from greenlet import greenlet
import time
def eat(name):print('%s eat 1' %name)  # 2g2.switch('taibai')  # 3time.sleep(3)print('%s eat 2' %name)  # 6g2.switch()  # 7def play(name):print('%s play 1' %name)  # 4g1.switch()  # 5print('%s play 2' %name)  # 8g1=greenlet(eat)
g2=greenlet(play)g1.switch('taibai')  # 1 切换到eat任务

协程模块gevent

gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

# gevent模块的几个用法
# 用法:
g1=gevent.spawn(func,1,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的,spawn是异步提交任务g2=gevent.spawn(func2)g1.join() # 等待g1结束g2.join() # 等待g2结束  有人测试的时候会发现,不写第二个join也能执行g2,是的,协程帮你切换执行了,但是你会发现,如果g2里面的任务执行的时间长,但是不写join的话,就不会执行完等到g2剩下的任务了# 或者上述两步合作一步:gevent.joinall([g1,g2])

使用time.sleep模拟程序中遇到的阻塞:

import gevent
import time
from threading import current_thread
def eat(name):print('%s eat 1' %name)print(current_thread().name)# gevent.sleep(2)time.sleep(2)print('%s eat 2' %name)def play(name):print('%s play 1' %name)print(current_thread().name)# gevent.sleep(1) # gevent.sleep(1)模拟的是gevent可以识别的io阻塞time.sleep(1)# time.sleep(1)或其他的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了print('%s play 2' %name)g1 = gevent.spawn(eat,'egon')
g2 = gevent.spawn(play,name='egon')
print(f'主{current_thread().name}')
g1.join()
g2.join()
# 结果: 
主MainThread
egon eat 1
MainThread
egon eat 2
egon play 1
MainThread
egon play 2

最终版本:

import gevent
from gevent import monkey
monkey.patch_all()  # 打补丁: 将下面的所有的任务的阻塞都打上标记
def eat(name):print('%s eat 1' %name)time.sleep(2)print('%s eat 2' %name)def play(name):print('%s play 1' %name)time.sleep(1)print('%s play 2' %name)g1 = gevent.spawn(eat,'egon')
g2 = gevent.spawn(play,name='egon')# g1.join()
# g2.join()
gevent.joinall([g1,g2])
# 结果:
egon eat 1
egon play 1
egon play 2
egon eat 2

负载均衡:就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行

Nginx:Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强。

一般在工作中我们都是进程+线程+协程的方式来实现并发,以达到最好的并发效果,如果是4核的cpu,一般起5个进程,每个进程中20个线程(5倍cpu数量),每个线程可以起500个协程,大规模爬取页面的时候,等待网络延迟的时间的时候,我们就可以用协程去实现并发。 并发数量 = 5 * 20 * 500 = 50000个并发,这是一般一个4cpu的机器最大的并发数。nginx在负载均衡的时候最大承载量就是5w个

单线程里的这20个任务的代码通常会既有计算操作又有阻塞操作,我们完全可以在执行任务1时遇到阻塞,就利用阻塞的时间去执行任务2。。。。如此,才能提高效率,这就用到了Gevent模块。

转载于:https://www.cnblogs.com/lifangzheng/p/11420036.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

不平衡数据下的机器学习方法简介

本文转自:http://baogege.info/2015/11/16/learning-from-imbalanced-data/ 引言 不管是在学术界还是工业界,不平衡学习已经吸引了越来越多的关注,不平衡数据的场景也出现在互联网应用的方方面面,如搜索引擎的点击预测&#xff08…

CSS预处理——LESS

LESS是什么? less是一门CSS预处理语言。由于CSS本身并不是程序式语言,不方便维护和扩展,没有变量、函数、作用域等概念。而LESS在CSS的基础语法之上,引入了变量、Mixin混入、运算以及函数等功能,大大简化了CSS的编写&a…

不均衡数据的处理方法

关于不均衡数据的处理方法,主要有以下几个方面: 1. 采样的方法 1.1 过采样,采集类标少的样本,达到平衡样本的目的。 方法一,简单的复制类标少的样本 方法二,生成人工样本(SMOTE方法&#xff09…

.mat,.txt,.csv 数据转换为weka中的arff格式及matlab和Weka之间相互转换格式

在RUSBoost和SMOTEBoost中提供了csv转换为arff格式的方法,详见CSVtoARFF.m http://www.mathworks.com/matlabcentral/fileexchange/37315-rusboost http://cn.mathworks.com/matlabcentral/fileexchange/37311-smoteboost function r CSVtoARFF (data, relation…

IT人不仅要提升挣钱能力,更要拓展挣钱途径

前几天我上班路上,和小区门口开车的师傅闲聊,发现他们虽然学历不高,但挣钱的途径不少,比如固定接送多位客户,然后能通过朋友圈拓展新客户,而且通过客户口口相传,也能不断拉到生意,算…

Class Imbalance Problem

本文转自:http://www.chioka.in/class-imbalance-problem/#comment-202282 What is the Class Imbalance Problem? It is the problem in machine learning where the total number of a class of data (positive) is far less than the total number of another c…

matlab中的类标转换程序

matlab中的类标转换程序 原始类标为Y,新类标为Y_new %进行排序,针对类标数目orig_labels sort(unique(Y)); Y_new Y;new_labels 1:length(orig_labels);for i1:length(orig_labels)Y_new(find(Yorig_labels(i)))Inf;Y_new(isinf(Y_new))new_labels(…

this关键字+super关键字

一.this关键字1.实例一:(1)需求:使用Java类描述一个动物;(2)实例:class Animal{ String name; //成员变量 String color; public Animal(String n,String c){ na…

python中的print

python3 中去除了print语句,加入print()函数实现相同的功能 print() 会在输出窗口中显示一些文本。 >>> print "hello,world!" SyntaxError: Missing parentheses in call to print >>> print("hello,world!") hello,world…

final+static

final final关键字顾名思义代表“最后的”,意味着不能被更改。它的定义,可以概括地分为以下三点: 被final修饰的类不能被继承;被final修饰的方法不能被重写;被final修饰的变量不能被改变。注:引用类型的变量…

程序代码编辑器和浏览器代码编辑器&代码可视化执行过程

tutorialspoint http://www.tutorialspoint.com/codingground.htm 1. Sublime Text :http://blog.l1n3.net/editor/sublime-text-introduce/ 下载 :http://www.sublimetext.com/3 2. Notepad https://notepad-plus-plus.org/zh/ 更多细节请查看 htt…

匿名对象+内部类

匿名对象 普通的类对象在使用时会定义一个类类型的变量,用来保存new出来的类所在的地址。而匿名类取消掉了这个变量,这个地址由编译器来处理,并且在new出来之后,它占用的内存会有JVM自动回收掉。后续无法再使用了。例如 public cl…

听技术播客:一边学Python编程一边学英语

本文转自:http://codingpy.com/article/recommended-python-podcasts/ 学技术的朋友一般都会关注不少技术博客(blog),但是关注技术播客(podcast)的人估计不会太多。这里一方面也是由于相关的播客数量&#…

mysql补充

mysql补充 mysql使用流程 开启服务端,mysqld或者net start mysqlcmd下键入mysql -u root -p,输入设置好的密码,连接mysql客户端show databases;展示所有的mysql仓库创建一个库:create database CRM;然后sho…

编程书单:十本Python编程语言的入门书籍

本文转自:http://codingpy.com/article/10-python-beginner-books/ 本文与大家分享一些Python编程语言的入门书籍,其中不乏经典。我在这里分享的,大部分是这些书的英文版,如果有中文版的我也加上了。有关书籍的介绍,大…

JavaScript异步

JavaScript异步类型 延迟类型:setTimeout、setInterval、setImmediate监听事件:监听new Image加载状态、监听script加载状态、监听iframe加载状态、Message带有异步功能类型: Promise、ajax、Worker、async/awaitJavaScript常用异步编程 Prom…

Sublime配置与各种插件

本文转自:http://www.cnblogs.com/yyhh/p/4232063.html Sublime Text 3 安装Package Control 点击View -> Show Console 在下方命令行内,输入以下命令。 import urllib.request,os;pfPackage Control.sublime-package;ippsublime.installed_packages_…

把Sublime Text 2打造成一个轻量级Python的IDE

本文转自:http://blog.l1n3.net/python/sublime-text-to-python-ide/ 因为这段时间迷上了Python,所以想吧Sublime Text 2弄成一个Python的简易IDE,Python自带的IDLE简直太难用!!!! 配置Python环…

数据库表操作、数据类型及完整性约束

数据库表操作、数据类型及完整性约束 库操作补充 数据库命名规则: 可以由字母、数字、下划线、@、#、$区分大小写唯一性不能使用关键字如 create select不能单独使用数字最长128位表操作补充 #语法: create table 表名…

算法第一次作业

1.代码规范(由于日后可能会用C和Java,就找了两种) Google C代码规范:https://blog.csdn.net/freeking101/article/details/78930381 Ggoogle Jave代码规范:https://www.jianshu.com/p/4e50269037ed 2.《数学之美》读后…