Python 从线程派生线程
我正在使用python 3.4.2来Python 从线程派生线程,python,multithreading,Python,Multithreading,我正在使用python 3.4.2来 让线程列表中的线程(t1)处理一些数据 让t1生成另一个线程(t2)来执行额外的处理 问题在于,似乎正确调用了proc\u q1并添加了t2\u q ID,但t2线程在exit\u标志设置为True之前没有从队列中拾取任务。为什么proc_q2从未被调用过 这里有一些模拟代码 import urllib.request import threading from queue import Queue from xml.etree import Elemen
proc\u q1
并添加了t2\u q ID,但t2线程在exit\u标志设置为True
之前没有从队列中拾取任务。为什么proc_q2
从未被调用过
这里有一些模拟代码
import urllib.request
import threading
from queue import Queue
from xml.etree import ElementTree as ET
from urllib.parse import urlparse
class Scanner(object):
@staticmethod
def proc_q1(thread_id, q1, q2):
while not exit_flag:
t1_lck.acquire()
if not q1.empty():
new_id = q1.get()
t1_lck.release()
# add id to t2_queue for threads2 to pick up
t2_lck.acquire()
t2_q.put(new_id)
t2_lck.release()
print('proc_q1 - new_id: {}'.format(new_id))
else:
t1_lck.release()
@staticmethod
def proc_q2(thread_id, q):
t2_lck.acquire()
if not q.empty():
new_id = q.get()
t2_lck.release()
print('proc_q2 - new_id: {}'.format(new_id))
else:
t2_lck.release()
class MyT1(threading.Thread):
def __init__(self, thread_id, q1, q2):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.q1 = q1
self.q2 = q2
def run(self):
print('Starting t1-thread {}'.format(self.thread_id))
Scanner.proc_q1(thread_id=self.thread_id, q1=self.q1, q2=self.q2)
print('Exiting t1-thread {}'.format(self.thread_id))
class MyT2(threading.Thread):
def __init__(self, thread_id, q):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.q = q
def run(self):
print('Starting t2-thread {}'.format(self.thread_id))
Scanner.proc_q2(thread_id=self.thread_id, q=self.q)
print('Exiting t2-thread {}'.format(self.thread_id))
# Create new threads
thread_pool_size = 5
t1_list = list()
t2_list = list()
t1_q = Queue(2 * thread_pool_size)
t2_q = Queue(2 * thread_pool_size)
t1_lck = threading.Lock()
t2_lck = threading.Lock()
exit_flag = False
for i in range(thread_pool_size):
t1 = MyT1(thread_id=i, q1=t1_q, q2 = t2_q)
t1.start()
t1_list.append(t1)
t2 = MyT2(thread_id=i, q=t2_q)
t2.start()
t2_list.append(t2)
# put data on the queue
t1_lck.acquire()
for i in range(10):
t1_q.put(i)
t1_lck.release()
# Wait for empty queue
while not (t1_q.empty() and t2_q.empty()):
pass
exit_flag = True
# wait for threads2 to finish
for t in t2_list:
t.join()
# wait for threads1 to finish
for t in t1_list:
t.join()
print("Done")
这是输出(脚本没有正确退出)
我认为日志输出给出了答案
MyT2线程在队列q2中的线程被填充之前退出
退出条件为:
@staticmethod
def proc_q2(thread_id, q):
...
if not q.empty():
...
最初,队列q2是空的,因此在队列有数据之前,all MyT2退出
因此,程序将永远在while循环中循环:
...
while not (t1_q.empty() and t2_q.empty()):
...
顺便说一句:
锁定:据我所知,队列的get()和put()方法是同步的。排队和解排队不需要获取锁
从文档中:
仅就您的主题发表评论:每个(!)进程都包含一个线程,它是最初运行的线程。没有此线程,您将无法执行任何操作,包括启动其他线程。顺便说一句,第一个线程通常并不特别。关于您的代码:它太长了,需要依赖外部服务来访问URL和下载内容。根据指导原则,用mock替换此代码以生成所需的最小示例。@UlrichEckhardt,我用mock更新了提供的代码。它仍然很长,但更易于管理。感谢您提供的可读性指导。
...
while not (t1_q.empty() and t2_q.empty()):
...
17.7. queue — A synchronized queue class