Python文档中的示例已扩展为可以从队列中进行工作。需要注意的更改是,此代码使用
concurrent.futures.wait而不是
concurrent.futures.as_completed允许在等待其他工作完成时开始新工作。
import concurrent.futuresimport urllib.requestimport timeimport queueq = queue.Queue()URLS = ['http://www.foxnews.com/', 'http://www.cnn.com/', 'http://europe.wsj.com/', 'http://www.bbc.co.uk/', 'http://some-made-up-domain.com/']def feed_the_workers(spacing): """ Simulate outside actors sending in work to do, request each url twice """ for url in URLS + URLS: time.sleep(spacing) q.put(url) return "DONE FEEDING"def load_url(url, timeout): """ Retrieve a single page and report the URL and contents """ with urllib.request.urlopen(url, timeout=timeout) as conn: return conn.read()# We can use a with statement to ensure threads are cleaned up promptlywith concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: # start a future for a thread which sends work in through the queue future_to_url = { executor.submit(feed_the_workers, 0.25): 'FEEDER DONE'} while future_to_url: # check for status of the futures which are currently working done, not_done = concurrent.futures.wait( future_to_url, timeout=0.25, return_when=concurrent.futures.FIRST_COMPLETED) # if there is incoming work, start a new future while not q.empty(): # fetch a url from the queue url = q.get() # Start the load operation and mark the future with its URL future_to_url[executor.submit(load_url, url, 60)] = url # process any completed futures for future in done: url = future_to_url[future] try: data = future.result() except Exception as exc: print('%r generated an exception: %s' % (url, exc)) else: if url == 'FEEDER DONE': print(data) else: print('%r page is %d bytes' % (url, len(data))) # remove the now completed future del future_to_url[future]
url两次获取的输出:
'http://www.foxnews.com/' page is 67574 bytes'http://www.cnn.com/' page is 136975 bytes'http://www.bbc.co.uk/' page is 193780 bytes'http://some-made-up-domain.com/' page is 896 bytes'http://www.foxnews.com/' page is 67574 bytes'http://www.cnn.com/' page is 136975 bytesDONE FEEDING'http://www.bbc.co.uk/' page is 193605 bytes'http://some-made-up-domain.com/' page is 896 bytes'http://europe.wsj.com/' page is 874649 bytes'http://europe.wsj.com/' page is 874649 bytes