一、名字解释
Python虚拟机:也叫解释器主循环,控制Python代码的执行。
多线程:类似单CPU系统中运行多个进程。 任意时刻,只能有一个线程在解释器中运行。
全局解释器锁(GIL):保证同一个时刻只有一个线程在运行。
二、thread
#!/usr/bin/env python
#import thread
from time import sleep, ctime
def loop0():
print "start loop 0 at:", ctime()
sleep(4)
print "end loop 0 at:", ctime()
def loop1():
print "start loop 1 at:", ctime()
sleep(2)
print "end loop 1 at:",ctime()
def main():
print "starting at:", ctime()
loop0()
loop1()
#thread.start_new_thread(loop0,())
#thread.start_new_thread(loop1,())
#sleep(6)
print "ending at:", ctime();
if __name__ == "__main__":
main()
没有thread:共耗时4+2=6秒
有thread,无锁:并发执行,共耗时4秒,需要主线程中手动sleep
#!/usr/bin/env python
import thread
from time import sleep, ctime
secs = [4,2]
def loop(nloop, nsec, lock):
print "start loop ", nloop," at:", ctime()
sleep(nsec)
print "end loop ", nloop, " at:", ctime()
lock.release()
def main():
print "starting at:", ctime()
nsecs = range(len(secs))
locks = []
for i in nsecs:
lock = thread.allocate_lock()
lock.acquire()
locks.append(lock)
for i in nsecs:
thread.start_new_thread(loop, (i, secs[i], locks[i]))
for i in nsecs:
while locks[i].locked(): pass
print "ending at:", ctime();
if __name__ == "__main__":
main()
有thread,有锁:共耗时4秒,主线程无需等待
三、threading
3种创建线程方法
1. 创建一个Thread的实例,传给它一个函数
2. 创建一个Thread的实例,传给它一个可调用的类对象
3. 从Thread派生出一个子类,创建一个这个子类的实例
#!/usr/bin/env python
import threading
from time import sleep, ctime
secs = [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 ", nloop, " at:", ctime()
sleep(nsec)
print "end loop ", nloop," at:", ctime()
def main():
print "starting at:", ctime()
nsecs = range(len(secs))
threads = []
for i in nsecs:
#t = threading.Thread(target=ThreadFunc(loop, (i, secs[i]), loop.__name__))
t = threading.Thread(target=loop,args=(i,secs[i]))
threads.append(t)
for i in nsecs:
threads[i].start()
for i in nsecs:
threads[i].join()
print "ending at:", ctime();
if __name__ == "__main__":
main()
上述代码是2种创建线程方法:执行结果一样,都是耗时4秒,主线程无需等待
四、threading.Lock
import threading
g_lock = threading.Lock()
g_lock.acquire()
g_lock.release()
import threading
g_tickets = 100
g_lock = threading.Lock()
def loop1():
global g_tickets
global g_lock
while True:
g_lock.acquire()
if g_tickets > 0:
print("thread 1 sell tickets: %d" % (g_tickets))
g_tickets = g_tickets - 1
else:
g_lock.release()
break
g_lock.release()
def loop2():
global g_tickets
global g_lock
while True:
g_lock.acquire()
if g_tickets > 0:
print("thread 2 sell tickets: %d" % (g_tickets))
g_tickets = g_tickets - 1
else:
g_lock.release()
break
g_lock.release()
def main():
t1 = threading.Thread(target=loop1, args=());
t2 = threading.Thread(target=loop2, args=())
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == "__main__":
main()
五、尽量使用threading,避免使用thread
1. threading模块更为先进,对线程支持更完善,使用thread模块可能会与threading出现冲突。
2. thread模块同步原语少(只有一个),threading模块有很多。
3. thread,当主线程结束时,所有线程都被强制结束掉;threading模块能确保重要的子线程退出口进程再退出。
六、Queue
import Queue
queue = Queue.Queue(maxsize=10)
queue.put(num)
num = queue.get()
queue.qsize()
import threading
import Queue
import random
import time
queue = Queue.Queue(maxsize=10)
def loop1():
while True:
if queue.qsize() < 10:
num = random.randint(1, 100)
print("produce num: %d" % (num))
queue.put(num)
time.sleep(random.randint(1,3))
def loop2():
while True:
if queue.qsize > 0:
num = queue.get()
print("consumer num: %d" % (num))
time.sleep(random.randint(1,3))
def main():
t1 = threading.Thread(target=loop1, args=())
t2 = threading.Thread(target=loop2, args=())
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == "__main__":
main()