Python代码代码的执行由python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程序,但任意时候,只有一个程序在CPU中运行。同样,虽然python解释器可以“运行”多个线程,但在任意时刻,只有一个线程在解释器中运行。
1 设置GIL
2 切换到一个线程去运行
3 运行:(a.指定数量的字节码指令,或者b.线程主动让出控制(可以调用time.sleep()))
4 把线程设置为睡眠状态
5 解锁GIL
6 重复以上所有步骤
没有线程支持的情况:
#! /usr/bin/env python
#coding=utf-8
from time import sleep,ctime
def loop0():
print("start loop 0 at:",ctime())
sleep(4)
print("loop 0 done at:",ctime())
def loop1():
print("Start loop 1 at:",ctime())
sleep(2)
print("loop 1 done at:",ctime())
def main():
print("starting main at:",ctime())
loop0()
loop1()
print("main done at:",ctime())
if __name__ == "__main__":
main()
>>>
('starting main at:', 'Fri Jul 25 20:45:51 2014')
('start loop 0 at:', 'Fri Jul 25 20:45:51 2014')
('loop 0 done at:', 'Fri Jul 25 20:45:55 2014')
('Start loop 1 at:', 'Fri Jul 25 20:45:55 2014')
('loop 1 done at:', 'Fri Jul 25 20:45:57 2014')
('main done at:', 'Fri Jul 25 20:45:57 2014')
可以看到单线程中的两个循环, 只有一个循环结束后另一个才开始。
Python中的多线程模块:thread,threading,Queue。
1
#! /usr/bin/env python
#coding=utf-8
import thread
from time import sleep,ctime
def loop0():
print("start loop 0 at:%s"%ctime())
sleep(4)
print("loop 0 done at:%s"%ctime())
def loop1():
print("Start loop 1 at:%s"%ctime())
sleep(2)
print("loop 1 done at:%s"%ctime())
def main():
print("start main at:%s"%ctime())
thread.start_new_thread(loop0,())
thread.start_new_thread(loop1,())
sleep(6)
print("main done at:%s"%ctime())
if __name__ == "__main__":
main()
>>>
start main at:Fri Jul 25 20:47:41 2014
Start loop 1 at:Fri Jul 25 20:47:41 2014
start loop 0 at:Fri Jul 25 20:47:41 2014
loop 1 done at:Fri Jul 25 20:47:43 2014
loop 0 done at:Fri Jul 25 20:47:45 2014
main done at:Fri Jul 25 20:47:47 2014
可以看到实际是运行了4秒两个loop就完成了。效率确实提高了。
2 threading模块
首先看一下threading模块中的对象:
Thread
Lock
RLock
Condition
Event
Semaphore
BoundedSemaphore
Timer
其中Thread类是你主要的运行对象,它有很多函数,用它你可以用多种方法来创建线程,常用的为以下三种。
1,
2,创建一个Thread实例,传给它一个可调用的类对象
3,从Thread派生出一个子类,创建一个这个子类的实例
Thread类的函数有:
getName(self)
isAlive(self)
isDaemon(self)
join(self, timeout=None) 程序挂起,直到线程结束,如果给出timeout,则最多阻塞timeout秒
run(self)
setDaemon(self, daemonic)
setName(self, name)
start(self)
下面看一个例子:(方法一:创建Thread实例,传递一个函数给它)
#! /usr/bin/env python
#coding=utf-8
import threading
from time import ctime,sleep
loops = [4,2]
def loop(nloop,nsec):
print("start loop %d at : %s"%(nloop,ctime()))
sleep(nsec)
print("loop %d done at: %s"%(nloop,ctime()))
def main():
print("start main at :%s"%ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(
target=loop,
args=(i,loops[i]))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print("main done at: %s"%ctime())
if __name__ == "__main__":
main()
>>>
start main at :Fri Jul 25 20:51:51 2014
start loop 0 at : Fri Jul 25 20:51:51 2014
start loop 1 at : Fri Jul 25 20:51:51 2014
loop 1 done at: Fri Jul 25 20:51:53 2014
loop 0 done at: Fri Jul 25 20:51:55 2014
main done at: Fri Jul 25 20:51:55 2014
可以看到第一个for循环,我们创建了两个线程,这里用到的是给Thread类传递了函数,把两个线程保存到threads列表中,第二个for循环是让两个线程开始执行。然后再让每个线程分别调用join函数,使程序挂起,直至两个线程结束。
另外的例子:(方法二:创建一个实例,传递一个可调用的类的对象)
#! /usr/bin/env python
#coding=utf-8
import threading
from time import ctime,sleep
loops = [4,2]
class ThreadFunc(object):
def __init__(self,func,args,name=''):
self.name = name
self.func = func
self.args = args
def __call__(self):
apply(self.func,self.args)
def loop(nloop,nsec):
print("start loop %d at : %s"%(nloop,ctime()))
sleep(nsec)
print("loop %d done at: %s"%(nloop,ctime()))
def main():
print("start main at :%s"%ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(
target=ThreadFunc(loop,(i,loops[i]),
loop.__name__))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print("main done at: %s"%ctime())
if __name__ == "__main__":
main()
最后的方法:(方法三:创建一个这个子类的实例)
#! /usr/bin/env python
#coding=utf-8
import threading
from time import ctime,sleep
loops = [4,2]
class MyThread(threading.Thread):
def __init__(self,func,args,name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
def run(self):
apply(self.func,self.args)
def loop(nloop,nsec):
print("start loop %d at : %s"%(nloop,ctime()))
sleep(nsec)
print("loop %d done at: %s"%(nloop,ctime()))
def main():
print("start main at :%s"%ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = MyThread(loop,(i,loops[i]),
loop.__name__)
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join()
print("main done at: %s"%ctime())
if __name__ == "__main__":
main()
REF:
1,Core Python Programming
2,http://blog.sina.com.cn/s/blog_4b5039210100esc1.html