前段时间我发布了一个关于从磁盘保存/检索后缀树的question。这最终工作正常,但现在构造非常缓慢,我现在不想弄乱Ukkonen的算法(线性构造)。
所以,我想进行并发插入以加速进程,而不必使树线程安全。
后缀树按其初始字符存储单词(查看我之前question上发布的图像),因此,Banana这个词位于根节点的“B”子节点中,Apple将位于'一个'孩子等等。因此,插入以'B'开头的单词绝不会干扰以'A'开头的插入。我的想法是为插入的单词集的每个初始字符设置一个线程:一个插入'A'的线程,另一个插入'B'的线程等等。
所以我在考虑一个Executer
类,只是在每个单词的队列中添加单词
Process
(如果它不存在,首先创建它。)
class Executer:
#...
def concurrent_insertion(word):
k = word[0]
processes.get(k, Process()).add(word)
# ...
类Process
是进行插入的类。每个Process
实例都是一个独立的主题,Queue
包含仍需要插入的单词。
在这个Process
类中,我遇到了麻烦,我猜它应该继承自threading.Thread
,因为每个实例都应该是一个线程,但是如何让它保持活着直到所有文本处理完成了吗?我的意思是,它应该插入其Queue
个单词中的单词,但是当Queue
为空时,线程不应该死,只要等待更多单词填满Queue
,“唤醒“并继续插入。
答案 0 :(得分:2)
线程在退出之前不会消亡,因此您可以使用while True
循环使它们保持活动状态。
通常的模式如下:
q = Queue.Queue() # word insertion queue
terminate = object() # sentinel value to tell a thread to terminate
def worker(q):
while True:
word = q.get() # block until next word is available
if word is terminate:
break
insert_word(word)
启动工作人员并向队列发送单词后,主线程需要等待所有工作完成,然后才能关闭工作人员。
for word in wordlist:
q.put(word)
for i in range(numthreads):
q.put(terminate) # terminate all the worker threads
for t in threadlist:
t.join() # wait for them all to finish
等待所有工作的另一种方法是使用q.task_done
和q.join
。有关如何使用它们的示例,请参见docs for the Queue module。