Python 中的多线程:卡在最后一个线程
Multi-threading in Python: Getting stuck at last thread
我有一个奇怪的情况,经过多次命中试验后无法解决。我正在使用多线程 (10) 来读取 url (100),它在大多数情况下工作正常,但在某些情况下,它会卡在最后一个线程。我等待它查看它是否 returns 并且花费了很多时间(1050 秒),而其余九个线程在 25 秒内返回。它显示我的代码有问题但无法弄清楚。有任何想法吗?
注意 1:守护线程和非守护线程都会发生这种情况。
注2:网址数量和话题发生变化。我尝试了 10-100 个不同数量的 URL 和 5-50 个不同的线程。
注意 3:URL 在大多数情况下是完全不同的。
import urllib2
import Queue
import threading
from goose import Goose
input_queue = Queue.Queue()
result_queue = Queue.Queue()
线程工作者:
def worker(input_queue, result_queue):
queue_full = true
while queue_full:
try:
url = input_queue.get(False)
read a url using urllib2 and goose
process it
result_queue.put(updated value)
except Queue.Empty:
queue_full = False
主要流程:
for url in urls:
input_queue.put(url)
thread_count = 5
for t in range(thread_count):
t = threading.Thread(target=worker, args= (input_queue, result_queue))
t.start()
for url in urls:
url = result_queue.get() # updates url
进程在最后一次 result_queue.get()
调用时被阻塞。
注意:我对我在这里做错了什么更感兴趣,以防有人指出?因为我倾向于认为我写了正确的代码,但显然事实并非如此。
例如,我将URL作为数字列表
import urllib2
import Queue
import threading
#from goose import Goose
input_queue = Queue.Queue()
result_queue = Queue.Queue()
def worker(input_queue, result_queue):
while not input_queue.empty():
try:
url = input_queue.get(False)
updated_value = int(url) * 9
result_queue.put(updated_value)
except Queue.Empty:
pass
urls = [1,2,3,4,5,6,7,8,9]
for url in urls:
input_queue.put(url)
thread_count = 5
for i in range(thread_count):
t = threading.Thread(target=worker, args= (input_queue, result_queue))
t.start()
t.join()
for url in urls:
try:
url = result_queue.get()
print url
except Queue.Empty:
pass
输出
9
18
27
36
45
54
63
72
81
您可以使用 concurrent.futures
中的 ThreadPoolExecutor
。
from concurrent.futures import ThreadPoolExecutor
MAX_WORKERS = 50
def worker(url):
response = requests.get(url)
return response.content
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
results = executor.map(worker, urls)
for result in results:
print(result)
我有一个奇怪的情况,经过多次命中试验后无法解决。我正在使用多线程 (10) 来读取 url (100),它在大多数情况下工作正常,但在某些情况下,它会卡在最后一个线程。我等待它查看它是否 returns 并且花费了很多时间(1050 秒),而其余九个线程在 25 秒内返回。它显示我的代码有问题但无法弄清楚。有任何想法吗?
注意 1:守护线程和非守护线程都会发生这种情况。
注2:网址数量和话题发生变化。我尝试了 10-100 个不同数量的 URL 和 5-50 个不同的线程。
注意 3:URL 在大多数情况下是完全不同的。
import urllib2
import Queue
import threading
from goose import Goose
input_queue = Queue.Queue()
result_queue = Queue.Queue()
线程工作者:
def worker(input_queue, result_queue):
queue_full = true
while queue_full:
try:
url = input_queue.get(False)
read a url using urllib2 and goose
process it
result_queue.put(updated value)
except Queue.Empty:
queue_full = False
主要流程:
for url in urls:
input_queue.put(url)
thread_count = 5
for t in range(thread_count):
t = threading.Thread(target=worker, args= (input_queue, result_queue))
t.start()
for url in urls:
url = result_queue.get() # updates url
进程在最后一次 result_queue.get()
调用时被阻塞。
注意:我对我在这里做错了什么更感兴趣,以防有人指出?因为我倾向于认为我写了正确的代码,但显然事实并非如此。
例如,我将URL作为数字列表
import urllib2
import Queue
import threading
#from goose import Goose
input_queue = Queue.Queue()
result_queue = Queue.Queue()
def worker(input_queue, result_queue):
while not input_queue.empty():
try:
url = input_queue.get(False)
updated_value = int(url) * 9
result_queue.put(updated_value)
except Queue.Empty:
pass
urls = [1,2,3,4,5,6,7,8,9]
for url in urls:
input_queue.put(url)
thread_count = 5
for i in range(thread_count):
t = threading.Thread(target=worker, args= (input_queue, result_queue))
t.start()
t.join()
for url in urls:
try:
url = result_queue.get()
print url
except Queue.Empty:
pass
输出
9
18
27
36
45
54
63
72
81
您可以使用 concurrent.futures
中的 ThreadPoolExecutor
。
from concurrent.futures import ThreadPoolExecutor
MAX_WORKERS = 50
def worker(url):
response = requests.get(url)
return response.content
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
results = executor.map(worker, urls)
for result in results:
print(result)