Python多线程编程中常用方法:
1、join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join([timeout]) timeout:可选参数,线程运行的最长时间
2、isAlive()方法:查看线程是否还在运行
3、getName()方法:获得线程名
4、setDaemon()方法:主线程退出时,需要子线程随主线程退出,则设置子线程的setDaemon()
Python线程同步:
(1)Thread的Lock和RLock实现简单的线程同步:
importthreadingimporttimeclassmythread(threading.Thread):def__init__(self,threadname):
threading.Thread.__init__(self,name=threadname)defrun(self):globalx
lock.acquire()foriinrange(3):
x= x+1time.sleep(1)PRintx
lock.release()if__name__=='__main__':
lock=threading.RLock()
t1=[]foriinrange(10):
t=mythread(str(i))
t1.append(t)
x=0foriint1:
i.start()
(2)使用条件变量保持线程同步:
#coding=utf-8importthreadingclassProducer(threading.Thread):def__init__(self,threadname):
threading.Thread.__init__(self,name=threadname)defrun(self):globalx
con.acquire()ifx == 10000:
con.wait()passelse:foriinrange(10000):
x= x+1con.notify()printx
con.release()classConsumer(threading.Thread):def__init__(self,threadname):
threading.Thread.__init__(self,name=threadname)defrun(self):globalx
con.acquire()ifx ==0:
con.wait()passelse:foriinrange(10000):
x= x-1con.notify()printx
con.release()if__name__=='__main__':
con=threading.Condition()
x=0
p= Producer('Producer')
c= Consumer('Consumer')
p.start()
c.start()
p.join()
c.join()printx
(3)使用队列保持线程同步:
#coding=utf-8importthreadingimportQueueimporttimeimportrandomclassProducer(threading.Thread):def__init__(self,threadname):
threading.Thread.__init__(self,name=threadname)defrun(self):globalqueue
i= random.randint(1,5)
queue.put(i)printself.getName(),'put %d to queue'%(i)
time.sleep(1)classConsumer(threading.Thread):def__init__(self,threadname):
threading.Thread.__init__(self,name=threadname)defrun(self):globalqueue
item=queue.get()printself.getName(),'get %d from queue'%(item)
time.sleep(1)if__name__=='__main__':
queue=Queue.Queue()
plist=[]
clist=[]foriinrange(3):
p= Producer('Producer'+str(i))
plist.append(p)forjinrange(3):
c= Consumer('Consumer'+str(j))
clist.append(c)forptinplist:
pt.start()
pt.join()forctinclist:
ct.start()
ct.join()
生产者消费者模式的另一种实现:
#coding=utf-8importtimeimportthreadingimportQueueclassConsumer(threading.Thread):def__init__(self, queue):
threading.Thread.__init__(self)
self._queue=queuedefrun(self):whileTrue:#queue.get() blocks the current thread until an item is retrieved.msg =self._queue.get()#Checks if the current message is the "quit"ifisinstance(msg, str)andmsg =='quit':#if so, exists the loop
break#"Processes" (or in our case, prints) the queue itemprint"I'm a thread, and I received %s!!"%msg#Always be friendly!print'Bye byes!'classProducer(threading.Thread):def__init__(self, queue):
threading.Thread.__init__(self)
self._queue=queuedefrun(self):#variable to keep track of when we startedstart_time =time.time()#While under 5 seconds..whiletime.time() - start_time < 5:#"Produce" a piece of work and stick it in the queue for the Consumer to processself._queue.put('something at %s'%time.time())#Sleep a bit just to avoid an absurd number of messagestime.sleep(1)#This the "quit" message of killing a thread.self._queue.put('quit')if__name__=='__main__':
queue=Queue.Queue()
consumer=Consumer(queue)
consumer.start()
producer1=Producer(queue)
producer1.start()
使用线程池(Thread pool)+同步队列(Queue)的实现方式:
#A more realistic thread pool example#coding=utf-8importtimeimportthreadingimportQueueimporturllib2classConsumer(threading.Thread):def__init__(self, queue):
threading.Thread.__init__(self)
self._queue=queuedefrun(self):whileTrue:
content=self._queue.get()ifisinstance(content, str)andcontent =='quit':
breakresponse=urllib2.urlopen(content)print'Bye byes!'defProducer():
urls=['http://www.python.org','http://www.yahoo.com''http://www.scala.org','http://cn.bing.com'#etc..]
queue=Queue.Queue()
worker_threads= build_worker_pool(queue, 4)
start_time=time.time()#Add the urls to processforurlinurls:
queue.put(url)#Add the 'quit' messageforworkerinworker_threads:
queue.put('quit')forworkerinworker_threads:
worker.join()print'Done! Time taken: {}'.format(time.time() -start_time)defbuild_worker_pool(queue, size):
workers=[]for_inrange(size):
worker=Consumer(queue)
worker.start()
workers.append(worker)returnworkersif__name__=='__main__':
Producer()
另一个使用线程池+Map的实现:
importurllib2frommultiprocessing.dummyimportPool as ThreadPool
urls=['http://www.python.org','http://www.python.org/about/','http://www.python.org/doc/','http://www.python.org/download/','http://www.python.org/community/']#Make the Pool of workerspool = ThreadPool(4)#Open the urls in their own threads#and return the resultsresults =pool.map(urllib2.urlopen, urls)#close the pool and wait for the work to finishpool.close()
pool.join()
参考:
http://blog.jobbole.com/58700/