我正在使用Java中的线程编写应用程序,并且我在循环中保持常量线程数有问题(新线程使用新数据传入)。 我使用ExecutorService来限制线程数,但我遇到了启动新线程的问题。
我有类似的东西:
ExecutorService execDownload = Executors.newFixedThreadPool(5);
UniqList<String> documentList = new UniqList<String>("startfile.txt");
Future<UniqList<String>> future;
while( !execDownload.isShutdown()) {
future = execDownload.submit(new Parser(documentList.get(i)));
i++;
try {
documentList.addAll(future.get());
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Parser是一个可调用对象,它返回UniqList。我将此列表中的元素添加到我的全局列表中,该列表是所有文档名称的集合。 问题是: 我想要同时运行恒定数量的解析器。如果我在程序启动之前知道文档的所有名称就会很简单,因为我应该调用ExecutorService的submit()方法,即100次,如果我有100个文件名,但我不知道文件的所有名称 - 名称通过调用此代码进行解析:
new Parser(documentList.get(i))
并且名称在文件内。 所以还有一次问题 - 当新数据到达时如何保持线程的常数?在上面的代码中,我只有一个Future Object,这是我认为最大的问题 - 我应该创建一系列期货吗?但是后来如何检测来自ExecutorService的某个线程刚刚返回一些新数据......
算法应该是(我认为):
正如你所看到的那样,就像递归一样。我认为这与解析网站,1个开始节点,第一级类别,第二级文章等相同。
链接或示例代码非常有用。谢谢。
答案 0 :(得分:0)
您的代码几乎是顺序的:future.get()会阻塞,直到任务完成,因此只要前一个任务正在运行,您就无法提交新任务。你可以:
答案 1 :(得分:0)
我建议放弃未来,并构建Parser来了解执行者:
execDownload.submit(new Parser(execDownload, documentList.get(i)));
让Parser将此“execDownload”ExecutorService存储为成员变量。
在Parser.run()结束时,当您拥有新解析的文档名称列表时,可以为它们创建新的解析器,并安排它们:
foreach (String newDoc: UniqList)
{
execDownload.submit(new Parser(execDownload, newDoc));
}