高效编程之 多线程Event
Event 简介
Event 事件 是线程间通信的最简单方法之一,主要用于线程同步。
处理机制
定义一个全局内置标志Flag,如果Flag为False,执行到 event.wait 时程序就会阻塞,如果Flag为True,event.wait 便不会阻塞
【注意如果处于阻塞状态,不管在哪使得Flag为true,wait都会继续执行】
接口
set() 将标志设置为True,并通知所有处于阻塞状态的线程恢复运行
clear() 将标志设置为False
isSet() 获取内置标志的状态,返回 True 或者 False
wait(timeout) 如果标志为False,将使得线程阻塞,如果为True,继续运行,默认为False
示例代码
示例代码--等通知
import threading
import time event = threading.Event() def chihuoguo(name):
# 等待事件,进入等待阻塞状态
print '%s 已经启动' % threading.currentThread().getName()
print '小伙伴 %s 已经进入就餐状态!'%name
time.sleep(1)
event.wait()
# 收到事件后进入运行状态
print '%s 收到通知了.' % threading.currentThread().getName()
print '小伙伴 %s 开始吃咯!'%name threads = []
thread1 = threading.Thread(target=chihuoguo, args=("a", ))
thread2 = threading.Thread(target=chihuoguo, args=("b", ))
threads.append(thread1)
threads.append(thread2) for thread in threads:
thread.start() time.sleep(0.1)
# 发送事件通知
print '主线程通知小伙伴开吃咯!'
event.set()
示例代码--互相通知
import threading
import time def producer():
print u'等人来买包子....'
event.wait()
#event.clear()
print event.isSet()
print u'chef:sb is coming for baozi...'
print u'chef:making a baozi for sb...'
time.sleep(5) print u'chef:你的包子好了...'
event.set() def consumer():
print u'chenchao:去买包子....'
event.set() time.sleep(2)
print 'chenchao:waiting for baozi to be ready...'
print event.wait()
print u'chenchao:哎呀真好吃....' event = threading.Event() p = threading.Thread(target=producer,args=())
c = threading.Thread(target=consumer,args=())
p.start()
c.start()
输出
等人来买包子....
chenchao:去买包子....
True
chef:sb is coming for baozi...
chef:making a baozi for sb...
chenchao:waiting for baozi to be ready...
True
chenchao:哎呀真好吃....
chef:你的包子好了...
上面实现了一个生产者-消费者模式,显然有错误,包子还没做好就吃上了。
稍微细心的缕下思路就会发现,消费者中的wait并没有阻塞线程,因为Flag此时为True
解决方法:
1. 用另一个 event2 来阻塞线程
2. 在生产者获得set时及时把Flag设置为False 【取消生产者中 event.clear() 的注释即可】
注意点1
import threading
event = threading.Event()
print(1)
print(event.wait()) # 打印也会使线程阻塞
print(2)
注意点2
import time
import threading def myfunc():
while 1:
time.sleep(1)
print(1) event = threading.Event() ts = []
if len(ts) > 2:
event.wait() # 此时阻塞,已经开启的线程将继续运行 for i in range(12):
t = threading.Thread(target=myfunc)
t.start()
ts.append(t)
实战案例
多线程验证代理ip的有效性
问题:计算机并不能无休止的增加线程,每台计算机都有自己的上限
### 计算机能够执行的最大线程数 def myfunc():
time.sleep(2) count = 0
while 1:
count += 1
print(count)
t = threading.Thread(target=myfunc)
t.start()
超过上限,就会报错
thread.error: can't start new thread
思路:设置最大线程数,当启动的线程超过最大限制时,阻塞,不再生成新线程,并且持续跟踪线程数,一旦减小或者小于某个阈值,就取消阻塞,继续生成线程
class MyTestProxy(object):
def __init__(self):
self.sFile = 'ip.txt'
self.dFile = 'alive.txt'
self.url = 'https://www.qiushibaike.com/text/'
self.threadmax = 500 # 最大线程数
self.threadmin = 400 # 最低线程数
self.timeout = 3
self.regex = re.compile('qiushibaike.com')
self.aliveList = [] self.event = threading.Event()
self.event2 = threading.Event()
self.lock = threading.Lock() self.run() def run(self):
with open(self.sFile, 'rb') as fp:
lines = fp.readlines()
self.ts = 0 # 初始化线程数
while lines:
if self.ts > self.threadmax:
self.event.clear()
self.event.wait() # 超过设定线程就阻塞 line = lines.pop()
t = threading.Thread(target=self.linkWithProxy, args=(line, ))
t.start()
self.lock.acquire()
self.ts += 1 # 启动一个就加1,ts 被其他线程一直在更新,所以加锁
self.lock.release() self.event2.wait() # 处理完毕后统一存储
with open(self.dFile, 'w') as fp:
for i in range(len(self.aliveList)):
fp.write(self.aliveList[i]) def act(self):
# 执行完一个线程就减1,因为同时执行,要加锁
self.lock.acquire()
self.ts -= 1
self.lock.release()
print(self.ts)
if self.ts < self.threadmin:
self.event.set() # 小于最低线程取消阻塞
if self.ts == 0:
self.event2.set() def linkWithProxy(self, line):
# 爬虫
server = line.strip()
# print(server)
protocol = line.split(':')[0]
opener = urllib2.build_opener(urllib2.ProxyHandler({protocol:server}))
urllib2.install_opener(opener) try:
response = urllib2.urlopen(self.url, timeout=self.timeout)
except:
return
else:
try:
str = response.read()
if self.regex.search(str):
# print(str)
print('%s connect success'%server)
print(response.geturl())
self.aliveList.append(line)
except:
return
finally:
self.act() if __name__ == '__main__':
time.clock()
tp = MyTestProxy()
print(time.clock())
效率还是不错的
参考资料:
http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html
高效编程之 多线程Event的更多相关文章
- C# 高效编程笔记2
C# 高效编程笔记2 1.理解GetHashCode()的陷阱 (1)作用:作为基于散列集合定义键的散列值,如:HashSet<T>,Dictionary<K,V>容器等 (2 ...
- C# 高效编程笔记1
C# 高效编程笔记1 1.使用属性而不是可访问的数据成员 (1).NET Framework中的数据绑定类仅支持属性,而不支持共有数据成员 (2)属性相比数据成员更容易修改 2.用运行时常量(read ...
- Python高效编程的19个技巧
初识Python语言,觉得python满足了我上学时候对编程语言的所有要求.python语言的高效编程技巧让我们这些大学曾经苦逼学了四年c或者c++的人,兴奋的不行不行的,终于解脱了.高级语言,如果做 ...
- 架构师速成-如何高效编程 for java
引子 赵云大喝一声,挺枪骤马杀入重围,左冲右突,如入无人之境.那枪浑身上下,若舞梨花:遍体纷纷,如飘瑞雪. 赵云是所有历史人物中我最喜欢的一个,如果放到现代,他走了it的道路,一定可以成为一个编程高手 ...
- C# winform编程中多线程操作控件方法
private void Form1_Load(object sender, EventArgs e) { Thread newthread = new Thread(new ThreadStart( ...
- IOS编程之多线程
IOS编程之多线程 目录 概述——对多线程的理解 IOS中实现多线程的三种方式 NSThread 线程创建 线程的同步与锁 线程间的交互 线程的操作方法 NSOperation and NSOpera ...
- C语言高效编程的几招(绝对实用,绝对经典)
编写高效简洁的C语言代码,是许多软件工程师追求的目标.废话不说,走起! 第一招:以空间换时间 计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题 eg.字符串的 ...
- [收藏转贴]struct探索·extern "C"含义探索 ·C++与C的混合编程·C 语言高效编程的几招
一.C/C++语言 struct深层探索 1.自然对界 struct是一种复合数据类型,其构成元素既可以是基本数据类型(如 int.long.float等)的变量,也可以是一些复合数据类型(如 arr ...
- [.NET] 《C# 高效编程》(一) - C# 语言习惯
C# 语言习惯 目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Con ...
随机推荐
- shell练习--关于关联数组自增统计判断的学习
今天在书上看到了一个关联数组 let statarray["$ftype"]++ 这样一个操作,用来做索引的自增统计,所以记下来 #!/bin/bash #统计文件类型 #关于关 ...
- python1--比较三个数值的大小
num1 = input("num1:")num2 = input("num2:")num3 = input("num3:")num = m ...
- DOM自定义属性操作
DOM标准 (一)核心DOM 可以操作一切结构化文档的API,包括HTML和XML,核心DOM是万能的,但又是繁琐的. (二)HTML DOM 专门操作HTML文档的简化版DOM AP ...
- sublime安装完插件后出现的一些问题
1.安装anaconda后代码前面出现小方框 解决办法:这是由于不符合PEP8代码规范,在空白地方右击,选择anaconda --> autoformat PEP8 Errors ,同时保证导入 ...
- Spring Cloud云架构 - SSO单点登录之OAuth2.0登录认证(1)
今天我们对OAuth2.0的整合方式做一下笔记,首先我从网上找了一些关于OAuth2.0的一些基础知识点,帮助大家回顾一下知识点: 一.oauth中的角色 client:调用资源服务器API的应用 O ...
- 用flask进行web开发
经理管理一个餐厅,推出每天都有特色菜的营销模式.他想根据一周中的每一天有一种特色菜. 客人想知道当天的特色菜是什么.另外再添加一个介绍页面.bios路径下,显示餐厅主人,厨师,服务生的简介. pyth ...
- [BZOJ1059]:[ZJOI2007]矩阵游戏(二分图匹配)
题目传送门 题目描述 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种 ...
- class 用法 函数变量的作用域
函数变量的作用域 1. 函数体内声明的变量 2. 参数中的变量 没有赋值的 function fn(a){} 赋值的,值不是变量 function fn(a=45){} 赋的值为变量 function ...
- cat输出多行内容到文件
输出格式是: cat > f1.sh <<end ...... end ----------------- == cat < f1.sh ## 同一行中的顺序可以改变 .... ...
- hashMap与 hashTable , ArrayList与linkedList 的区别(详细)
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个 ...