python多线程理解
在发送网络请求的过程中,单个请求的速度总是有着很大的限制,而任务往往需要以更快的速度去执行,这时多线程就是一个很好地选择。python已经给我们封装好了多线程库thread和threading。
thread:比较底层的模块
threading:Higher-level threading interface
ps:建议使用threading模块
- 高级别的threading模块更为先进,对线程的支持更为完善
- 低级别的thread模块同步原语很少
- thread模块对线程什么时候结束完全没有控制,当主线程结束时,所有线程都会强制结束
thread
模块函数
start_new_thread(function, args,kwargs=None): 产生新的线程,args是function的参数,没有时写(),kwargs用来调用这个函数
allocate_lock(): 分配锁,LockType类型
exit(): 让线程退出
LockType的操作
acquire(wait=None):尝试获取锁
locked(): 获取了锁返回True,没有返回False
release():释放锁
Demo1
$ cat t1.py
import thread
from time import sleep
def a():
print "a start"
sleep(2)
print "a end"
def b():
print "b start"
sleep(2)
print "b end"
def main():
thread.start_new_thread(a,())
thread.start_new_thread(b,())
print "all done"
if __name__ == "__main__":
main()
$ python t1.py
all done
b start
a start
最终会发现,每一次运行出来的结果都有可能不同,但是绝对不会出现“a end”和“b end”。这是为什么呢,这里没有写让主线程停下来等所有子线程结束后再继续运行的代码,所以main线程在执行完print "all done"就关闭了a和b两个线程。怎么办呢,可以在这里加一个sleep等待子进程执行完毕后再退出。
Demo2: thread -- 多线程的演示 by sleep
$ cat t2.py
import thread
from time import sleep
def a():
print "a start"
sleep(2)
print "a end"
def b():
print "b start"
sleep(2)
print "b end"
def main():
thread.start_new_thread(a,())
thread.start_new_thread(b,())
sleep (4) ----防止主进程过早退出,加sleep等待子进程执行完毕后再推出
print "all done"
if __name__ == "__main__":
main()
$ python t1.py
b start
a start
a end
b end
all done
但是假设我们不知道子进程执行的时间怎么办,这就是锁的用武之地了。因为使用锁要比使用sleep()函数更为合理。如下所示:
Demo3: thread -- 多线程演示 by lock
实现方式为: 主线程初始化两个锁,分别传给两个函数,两个函数在执行完自己的代码后释放锁,主线程一直在轮询这个锁有没有释放,如果释放了就退出。
def a(lock, nsec):
print "a starting at :", ctime()
sleep(nsec)
lock.release() -- 执行完之后释放锁
print "a end", ctime()
def b(lock, nsec):
print "b starting at :", ctime()
sleep(nsec)
lock.release() -- 执行完之后释放锁
print "b end", ctime()
def main():
print "Demo Starting at:", ctime()
locks = []
# Initialize lock -- 主线程先获取两个锁,占为己有
for i in range(2):
lock = thread.allocate_lock()
lock.acquire()
locks.append(lock)
# 每个进程分配一个锁
thread.start_new_thread(a, (locks[0],2))
thread.start_new_thread(b, (locks[1],4))
for i in range(2): #一直在轮询,看锁有没有释放
while locks[i].locked(): pass
print "all done at:", ctime()
最后的结果为:
$ python thread_demo.py
Demo Starting at: Fri Aug 29 22:03:01 2014
a starting at : Fri Aug 29 22:03:01 2014
b starting at : Fri Aug 29 22:03:01 2014
a end Fri Aug 29 22:03:03 2014
b end Fri Aug 29 22:03:05 2014
all done at: Fri Aug 29 22:03:05 2014
不难发现,thread库的同步机制比较难用,一切都需要主进程来处理。并且没有守护进程,主进程一退,整个世界都会变得很清静。而threading库给我们提供了守护进程。下面就来看看threading的简单用法。
threading
threading提供了Thread类,还提供了很多非常好用的同步机制。感觉重点了解Thread类就可以,多线程,也就是通过Thread类的多个实例。 类的主要方法有:
start():开始线程的执行。thread库里里面,是没有办法控制线程的开始的
join(timeout=None): 等待线程结束,有点类似Demo3中的轮询
run():定义线程的功能
感觉上面是比较重要的,立马就会用到的。还有一些其他的:
getName():获取线程名
setName(name):设置线程名
isAlive(): 返回bool 表示线程是否在运行中
activeCount():返回运行中的线程数
currentThread():返回当前线程对象
enumerate():返回当前活动线程的列表
isDaemon(): 返回线程的Daemon标志
setDaemon(daemonic): 设置线程的Daemon标志,一般在start()函数前调用
settrace(func):为所有线程设置跟踪函数
setprofile(func): 为所有线程设置profile函数
Demo4 -- threading演示
def loop(i, nsec):
print "thread %d starting at : %s" %(i, ctime())
sleep(nsec)
print "thread %d end at : %s" %(i, ctime())
def main():
threads = []
loops = [2, 4]
# 实例化进程
for i in range(len(loops)):
t = threading.Thread(target = loop, args = (i, loops[i]))
threads.append(t)
for i in range(len(loops)):
threads[i].start()
for i in range(len(loops)):
threads[i].join()
print "all done"
最后的结果为:
thread 0 starting at : Sun Aug 31 13:31:28 2014
thread 1 starting at : Sun Aug 31 13:31:28 2014
thread 0 end at : Sun Aug 31 13:31:30 2014
thread 1 end at : Sun Aug 31 13:31:32 2014
all done
对Daemon线程理解:
A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.
线程可以被标识为"Daemon线程",Daemon线程表明整个Python主程序只有在Daemon子线程运行时可以退出。该属性值继承自父线程,可通过setDaemon()函数设定该值。
Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
注意:Daemon线程会被粗鲁的直接结束,它所使用的资源(已打开文件、数据库事务等)无法被合理的释放。因此如果需要线程被优雅的结束,请设置为非Daemon线程,并使用合理的信号方法,如事件Event。
Python主程序当且仅当不存在非Daemon线程存活时退出。
即:主程序等待所有非Daemon线程结束后才退出,且退出时会自动结束(很粗鲁的结束)所有Daemon线程。
亦理解为:Daemon设置为子线程是否随主线程一起结束,默认为False。如果要随主线程一起结束需要设置为True。
Daemon线程用途:
Daemons 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, we have to keep track of them, and tell them to exit, before our program can completely quit. By setting them as daemon threads, we can let them run and forget about them, and when our program quits, any daemon threads are killed automatically.
Daemon线程当且仅当主线程运行时有效,当其他非Daemon线程结束时可自动杀死所有Daemon线程。如果没有Daemon线程的定义,则必须手动的跟踪这些线程,在程序结束前手动结束这些线程。通过设置线程为Daemon线程,则可以放任它们运行,并遗忘它们,当主程序结束时这些Daemon线程将自动被杀死。
python多线程理解的更多相关文章
- Python的多线程理解,转自虫师https://www.cnblogs.com/fnng/p/3670789.html
多线程和多进程是什么自行google补脑 对于python 多线程的理解,我花了很长时间,搜索的大部份文章都不够通俗易懂.所以,这里力图用简单的例子,让你对多线程有个初步的认识. 单线程 在好些年前的 ...
- 彻底理解Python多线程中的setDaemon与join【配有GIF示意】
在进行Python多线程编程时, join() 和 setDaemon() 是最常用的方法,下面说说两者的用法和区别. 1.join () 例子:主线程A中,创建了子线程B,并且在主线程A中调用了B. ...
- python多线程学习记录
1.多线程的创建 import threading t = t.theading.Thread(target, args--) t.SetDeamon(True)//设置为守护进程 t.start() ...
- python多线程
python多线程有两种用法,一种是在函数中使用,一种是放在类中使用 1.在函数中使用 定义空的线程列表 threads=[] 创建线程 t=threading.Thread(target=函数名,a ...
- python 多线程就这么简单(转)
多线程和多进程是什么自行google补脑 对于python 多线程的理解,我花了很长时间,搜索的大部份文章都不够通俗易懂.所以,这里力图用简单的例子,让你对多线程有个初步的认识. 单线程 在好些年前的 ...
- Python多线程和Python的锁
Python多线程 Python中实现多线程有两种方式,一种基于_thread模块(在Python2.x版本中为thread模块,没有下划线)的start_new_thread()函数,另一种基于th ...
- 关于python多线程编程中join()和setDaemon()的一点儿探究
关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧. 首先是编写实验的基础代码,创建一个名为MyThread的 ...
- python多线程机制
Python中的线程从一开始就是操作系统的原生线程.而Python虚拟机也同样使用一个全局解释器锁(Global Interpreter Lock,GIL)来互斥线程多Python虚拟机的使用. GI ...
- Python多线程及其使用方法
[Python之旅]第六篇(三):Python多线程及其使用方法 python 多线程 多线程使用方法 GIL 摘要: 1.Python中的多线程 执行一个程序,即在操作系统中开启了一个进 ...
随机推荐
- Docker学习总结(4)——Docker镜像与容器命令
Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机).bare metal. ...
- NIO框架之MINA源代码解析(一):背景
"你们的agent占了好多系统的port.把我们的非常多业务系统都给整死了,给我们造成了非常大的损失.要求你们的相关领导下周过来道歉" -- 来自我们的一个客户. ...
- hadoop-06-http服务
hadoop-06-http服务 su root service httpd status service httpd stop vi /etc/httpd/conf/httpd.conf 修改:Do ...
- APP-午饭去哪吃
走到这个快节奏的城市中.部门聚餐.朋友吃饭这些都是日常生活中时有发生的事情,往往吃的东西都是千篇一律,图的也仅仅剩下的是环境了.那么.非常纠结常常去的地方,怎么办呢?来吧.我们随机摇一个吧! wate ...
- 页面头部带loading进度指示的jQuery滚动页面特效
这是一款非常有用且效果非常酷的jQuery页面头部带loading进度指示的滚动页面特效. 该特效在页面滚动的时候页面头部有Loading进度条指示当前页面滚动的位置,这能够让用户知道当前阅读的地方距 ...
- Datazen图表创建和公布
Datazen是被微软收购的移动端全平台的数据展现解决方式.此篇主要介绍怎样创建和公布图表. 如前面介绍,Datazen图表的创建和公布是通过Publisher的应用,它是Windows 8应用 ...
- layer是什么
layer是什么 总结 layer就是一个web弹框 简介 layer是一款web弹层组件,致力于服务各个水平段的开发人员. 可以让你想到即可做到的web弹窗 概述 [1] layer,一个可以让你 ...
- 6. Intellij Idea 2017创建web项目及tomcat部署实战
转自:https://www.cnblogs.com/shindo/p/7272646.html 相关软件:Intellij Idea2017.jdk16.tomcat7 Intellij Idea直 ...
- Clion远程开发
2018.3 开始Clion可以支持远程开发了 官网教程如下: https://www.jetbrains.com/help/clion/remote-projects-support.html ...
- List exercise
The slice operator can take a third argument that determines the step size, so t[::2] creates a list ...