Python多线程编程中常用方法:
1、join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join([timeout]) timeout:可选参数,线程运行的最长时间
2、isAlive()方法:查看线程是否还在运行
3、getName()方法:获得线程名
4、setDaemon()方法:主线程退出时,需要子线程随主线程退出,则设置子线程的setDaemon()
Python线程同步:
(1)Thread的Lock和RLock实现简单的线程同步:
import threading
class A(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(0,10):
print("我是线程A")
class B(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
for i in range(0,10):
print("我是线程B")
t1 = A()
t1.start()
t2=B()
t2.start()
(2)使用条件变量保持线程同步:# coding=utf-8
import threading
class Producer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
global x
con.acquire()
if x == 10000:
con.wait()
pass
else:
for i in range(10000):
x = x+1
con.notify()
print (x)
con.release()
class Consumer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
global x
con.acquire()
if x == 0:
con.wait()
pass
else:
for i in range(10000):
x = x-1
con.notify()
print (x)
con.release()
if __name__ == '__main__':
con = threading.Condition()
x = 0
p = Producer('Producer')
c = Consumer('Consumer')
p.start()
c.start()
p.join()
c.join()
print(x)
(3)使用队列保持线程同步:
队列说明:模块queue
创建队列:q = queue.Queue(),括号中间传递值来指定队列的大小,例如q=queue.Queue(2)表示指定队列的大小为2;
q.empty()判断队列是否为空,输出True和False;q.full()判断队列是否满了,输出True和False;
q.put()放一个元素进队列,q.get()取一个元素出队列,遵从先进先出的原则;
get_nowait()立即取出一个元素,不等待;put_nowait()立即放入一个元素,不等待;
join()阻塞调用线程,直到队列中的所有任务被处理掉;q.qsize()返回队列中元素的个数
# coding=utf-8
import threading
import queue
import time
import random
class Producer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
global queue
i = random.randint(1,5)
queue.put(i)
print (self.getName(),' put %d to queue' %(i))
time.sleep(1)
class Consumer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
global queue
item = queue.get()
print (self.getName(),' get %d from queue' %(item))
time.sleep(1)
if __name__ == '__main__':
queue = queue.Queue()
plist = []
clist = []
for i in range(3):
p = Producer('Producer'+str(i))
plist.append(p)
for j in range(3):
c = Consumer('Consumer'+str(j))
clist.append(c)
for pt in plist:
pt.start()
pt.join()
for ct in clist:
ct.start()
ct.join()
生产者消费者模式的另一种实现:
# coding=utf-8
import time
import threading
import queue
class Consumer(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
while True:
# queue.get() blocks the current thread until an item is retrieved.
msg = self._queue.get()
# Checks if the current message is the "quit"
if isinstance(msg, str) and msg == 'quit':
# if so, exists the loop
break
# "Processes" (or in our case, prints) the queue item
print ("I'm a thread, and I received %s!!" % msg)
# Always be friendly!
print ('Bye byes!')
class Producer(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
# variable to keep track of when we started
start_time = time.time()
# While under 5 seconds..
while time.time() - start_time < 5:
# "Produce" a piece of work and stick it in the queue for the Consumer to process
self._queue.put('something at %s' % time.time())
# Sleep a bit just to avoid an absurd number of messages
time.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-8
import time
import threading
import queue
import urllib.request
class Consumer(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self._queue = queue
def run(self):
while True:
content = self._queue.get()
if isinstance(content, str) and content == 'quit':
break
response = urllib.request.urlopen(content)
print ('Bye byes!')
def Producer(queue):
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 process
for url in urls:
queue.put(url)
# Add the 'quit' message
for worker in worker_threads:
queue.put('quit')
for worker in worker_threads:
worker.join()
print ('Done! Time taken: {}'.format(time.time() - start_time))
def build_worker_pool(queue, size):
workers = []
for _ in range(size):
worker = Consumer(queue)
worker.start()
workers.append(worker)
return workers
if __name__ == '__main__':
queue = queue.Queue()
Producer(queue)
import urllib.request
from multiprocessing.dummy import Pool 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 workers
pool = ThreadPool(4)
# Open the urls in their own threads
# and return the results
results = pool.map(urllib.request.urlopen,urls)
#close the pool and wait for the work to finish
pool.close()
pool.join()