python多线程之threading模块
threading模块中的对象

- 其中除了Thread对象以外,还有许多跟同步相关的对象
- threading模块支持守护线程的机制
Thread对象

直接调用法
import threading
import time def sayhi(num): #定义每个线程要运行的函数 print("running on number:%s" %num) time.sleep(3) if __name__ == '__main__': t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例 t1.start() #启动线程
t2.start() #启动另一个线程 print(t1.getName()) #获取线程名
print(t2.getName())
继承类方式
import threading
import time class MyThread(threading.Thread):
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num def run(self):#定义每个线程要运行的函数 print("running on number:%s" %self.num) time.sleep(3) if __name__ == '__main__': t1 = MyThread(1)
t2 = MyThread(2)
t1.start()
t2.start()
注意:当要启动这个线程时,只会去调用这个类的run方法,因此,在定义子类时,一定要去重写父类的run方法,不然在线程启动后,该线程不会做任何事情。
join和daemon问题
- join:为了让主线程等待子线程结束。
- daemon:将线程设置为守护线程,该线程就会变成设置其为守护线程的线程的“仆人”,当其“主人”要退出时,其不管自己的任务是否完成,都会跟着“主人一起退出”。
Some threads do background tasks, like sending keepalive packets, or performing periodic garbage collection, or whatever. These are only useful when the main program is running, and it's okay to kill them off once the other, non-daemon, threads have exited.
Without daemon threads, you'd have to keep track of them, and tell them to exit, before your program can completely quit. By setting them as daemon threads, you can let them run and forget about them, and when your program quits, any daemon threads are killed automatically.
#_*_coding:utf-8_*_
__author__ = 'Alex Li' import time
import threading def run(n): print('[%s]------running----\n' % n)
time.sleep(2)
print('--done--') def main():
for i in range(5):
t = threading.Thread(target=run,args=[i,])
t.start()
t.join(1)
print('starting thread', t.getName()) m = threading.Thread(target=main,args=[])
m.setDaemon(True) #将main线程设置为Daemon线程,它做为程序主线程的守护线程,当主线程退出时,m线程也会退出,由m启动的其它子线程会同时退出,不管是否执行完任务
m.start()
m.join(timeout=2)
print("---main thread done----")
Lock对象(线程锁--互斥锁Mutex)
线程锁与GIL的区别
很多人都不明白python已经有了一个GIL了,怎么还搞一个线程锁。先给个图:

首先要明确,线程锁是用户级别的锁机制,跟解释器的GIL没有任何关系,也不会互相有任何。接下来,大家要注意GIL的描述,它说的是“同一时刻只会有一个线程在cpu上执行”,这并不代表着这个占用cpu的线程之行完后再去执行另一个线程(如果是这样的话,那就不存在多线程的说法了),那么线程很可能会在执行任务中,被打断,让出cpu(python的线程机制是调用的c的线程接口,即原生线程的调用,因此,调度方案是由操作系统决定的)。
即然是这样的,回到用python创建的线程中。上图中,红色的线程的任务是做“加1”操作,由于这个“加一”的操作并不是“原子操作”,所以,在执行时,很可能被打断。如果这时打断红色的线程是蓝色的线程,它同样是利用count(共享资源),那么由于红色的进程没有完成其任务,所以,蓝色的进程读到的count的跟红色的进程读到的值一样(即count=0)。这时,蓝色的线程正常执行,完成“加1”任务(count=1),之后,红色的进程再重新恢复执行,但当下,其拿到的“count=0”,然后完成“加1”任务,即这时“count=1”。
回过头了,我们起初想要的结果是“count=2”,而不是“count=1”。在这个过程中,我们是遵守GIL规则的,但是还是很可能会出现上述现象,这就是我说的,线程锁是用户级别的锁,跟GIL没有关系,我要考虑的业务逻辑是否需要做“原子操作”的问题,如果需要,就需要线程锁机制。
基本使用方法
import time
import threading def addNum():
global num #在每个线程中都获取这个全局变量
print('--get num:',num )
time.sleep(1)
lock.acquire() #修改数据前加锁
num -=1 #对此公共变量进行-1操作
lock.release() #修改后释放 num = 100 #设定一个共享变量
thread_list = []
lock = threading.Lock() #生成全局锁
for i in range(100):
t = threading.Thread(target=addNum)
t.start()
thread_list.append(t) for t in thread_list: #等待所有线程执行完毕
t.join() print('final num:', num )
RLock(递归锁)
说白了就是要在大锁中再次添加锁的机制
基本使用方法
import threading,time def run1():
print("grab the first part data")
lock.acquire()
global num
num +=1
lock.release()
return num
def run2():
print("grab the second part data")
lock.acquire()
global num2
num2+=1
lock.release()
return num2
def run3():
lock.acquire()
res = run1()
print('--------between run1 and run2-----')
res2 = run2()
lock.release()
print(res,res2) if __name__ == '__main__': num,num2 = 0,0
lock = threading.RLock()
for i in range(10):
t = threading.Thread(target=run3)
t.start() while threading.active_count() != 1:
print(threading.active_count())
else:
print('----all threads done---')
print(num,num2)
semaphore对象(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据 ,比如厕所有3个坑,那最多只允许3个人上厕所,后面的人只能等里面有人出来了才能再进去。
import threading,time def run(n):
semaphore.acquire()
time.sleep(1)
print("run the thread: %s\n" %n)
semaphore.release() if __name__ == '__main__': num= 0
semaphore = threading.BoundedSemaphore(5) #最多允许5个线程同时运行
for i in range(20):
t = threading.Thread(target=run,args=(i,))
t.start() while threading.active_count() != 1:
pass #print threading.active_count()
else:
print('----all threads done---')
print(num)
timer对象
This class represents an action that should be run only after a certain amount of time has passed
Timers are started, as with threads, by calling their start() method. The timer can be stopped (before its action has begun) by calling thecancel() method. The interval the timer will wait before executing its action may not be exactly the same as the interval specified by the user.
def hello():
print("hello, world") t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
Events对象
An event is a simple synchronization object;
the event represents an internal flag, and threads
can wait for the flag to be set, or set or clear the flag themselves.
event = threading.Event()
# a client thread can wait for the flag to be set
event.wait()
# a server thread can set or reset it
event.set()
event.clear()
If the flag is set, the wait method doesn’t do anything.
If the flag is cleared, wait will block until it becomes set again.
Any number of threads may wait for the same event.
通过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程做交通指挥灯,生成几个线程做车辆,车辆行驶按红灯停,绿灯行的规则。
import threading,time
import random
def light():
if not event.isSet():
event.set() #wait就不阻塞 #绿灯状态
count = 0
while True:
if count < 10:
print('\033[42;1m--green light on---\033[0m')
elif count <13:
print('\033[43;1m--yellow light on---\033[0m')
elif count <20:
if event.isSet():
event.clear()
print('\033[41;1m--red light on---\033[0m')
else:
count = 0
event.set() #打开绿灯
time.sleep(1)
count +=1
def car(n):
while 1:
time.sleep(random.randrange(10))
if event.isSet(): #绿灯
print("car [%s] is running.." % n)
else:
print("car [%s] is waiting for the red light.." %n)
if __name__ == '__main__':
event = threading.Event()
Light = threading.Thread(target=light)
Light.start()
for i in range(3):
t = threading.Thread(target=car,args=(i,))
t.start()
python多线程之threading模块的更多相关文章
- “死锁” 与 python多线程之threading模块下的锁机制
一:死锁 在死锁之前需要先了解的概念是“可抢占资源”与“不可抢占资源”[此处的资源可以是硬件设备也可以是一组信息],因为死锁是与不可抢占资源有关的. 可抢占资源:可以从拥有他的进程中抢占而不会发生副作 ...
- python 多线程编程之threading模块(Thread类)创建线程的三种方法
摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...
- python多线程之Threading
什么是线程? 线程是操作系统内核调度的基本单位,一个进程中包含一个或多个线程,同一个进程内的多个线程资源共享,线程相比进程是“轻”量级的任务,内核进行调度时效率更高. 多线程有什么优势? 多线程可以实 ...
- python多线程之threading、ThreadPoolExecutor.map
背景: 某个应用场景需要从数据库中取出几十万的数据时,需要对每个数据进行相应的操作.逐个数据处理过慢,于是考虑对数据进行分段线程处理: 方法一:使用threading模块 代码: # -*- codi ...
- python 线程之 threading(四)
python 线程之 threading(三) http://www.cnblogs.com/someoneHan/p/6213100.html中对Event做了简单的介绍. 但是如果线程打算一遍一遍 ...
- python 线程之 threading(三)
python 线程之 threading(一)http://www.cnblogs.com/someoneHan/p/6204640.html python 线程之 threading(二)http: ...
- python并发编程之threading线程(一)
进程是系统进行资源分配最小单元,线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.进程在执行过程中拥有独立的内存单元,而多个线程共享内存等资源. 系列文章 py ...
- {Python之线程} 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Threading模块 九 锁 十 信号量 十一 事件Event 十二 条件Condition(了解) 十三 定时器
Python之线程 线程 本节目录 一 背景知识 二 线程与进程的关系 三 线程的特点 四 线程的实际应用场景 五 内存中的线程 六 用户级线程和内核级线程(了解) 七 python与线程 八 Thr ...
- <python的线程与threading模块>
<python的线程与threading模块> 一 线程的两种调用方式 threading 模块建立在thread 模块之上.thread模块以低级.原始的方式来处理和控制线程,而thre ...
随机推荐
- Django signal 信号机制的使用
Django中提供了"信号调度",用于在框架执行操作时解耦,当某些动作发生的时候,系统会根据信号定义的函数执行相应的操作 一.Django中内置的 signal 类型主要包含以下几 ...
- win10无法访问samba共享
地址: https://blog.csdn.net/xiaohuixing16134/article/details/79601064?utm_source=blogxgwz1 问题描述:配置好sam ...
- 了解Kafka
Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能 高吞吐率. ...
- 编写一致的符合习惯的javascript
本文转自我司的编码规范~ ==== 引言 将要叙述的这些原则旨对javascript开发的风格做指导,并非指定性的规则需绝对服从.如果需要找出一条必须遵循的原则,应该是保持代码的一致性和风格统一. 除 ...
- git小白使用教程(一)
本文所涉及命令基本可以涵盖日常开发场景, 对于开发者平时很少使用的命令不再列举,这样不至于让刚刚使用git的小伙伴们看的脑袋大...如有特殊使用可以联系我单独回复. 首先通过一张图了解git的工作流程 ...
- 聊聊jvm系列
http://blog.csdn.net/column/details/talk-about-jvm.html
- Windows平台下Git服务器搭建--------gitblit
Windows(server)平台下Git服务器搭建 第一步:下载Java,安装,配置环境变量. 第二步:下载Gitblit.下载地址:http://www.gitblit.com/ 第三步:解压缩下 ...
- Spring Security构建Rest服务-1001-spring social开发第三方登录之spring social基本原理
OAuth协议是一个授权协议,目的是让用户在不将服务提供商的用户名密码交给第三方应用的条件下,让第三方应用可以有权限访问用户存在服务提供商上的资源. 接着上一篇说的,在第三方应用获取到用户资源后,如果 ...
- rabbit服务器挂掉以后,保证队列消息还存在(tp框架)(第三篇)
上接 第二篇 : http://www.cnblogs.com/spicy/p/7921870.html 第二篇解决了 如果其中一个worker挂掉了啦,如何保证消息不丢掉,并重新分发给其他worke ...
- 关于mpvue和wafer2-client-sdk的 微信登录失败,请检查网络状态
关于mpvue和wafer2-client-sdk的登录使用. 错误形式: <script> // import {get} from './util' import qcloud fro ...