我正在研究一个访问页面并提取链接以查找特定域的Web爬网程序,如果找不到,它将查看提取的链接并重复直到达到页面限制或找到页面为止。我发现自己正在努力提出合理的逻辑,以使该僵尸程序在提取链接后继续让任务排队,因为该任务正在快速完成,并且没有足够的时间来提交新提取的链接。我该如何实施,使搜寻器在没有执行程序的情况下等待其关闭,然后再关闭执行器?我已经包括了我的多线程实现的基本概述。我将最大线程数设置为3,并提交example.com 10次(种子域)
Spawn Thread访问站点并提取链接,然后将其返回为字符串。我的问题是我需要能够获得这些结果,然后将其放入队列。但是到那时队列已经完成。有什么建议么?
更新为了澄清,我的问题是,当我提交种子并获得结果时,我无法获取它来继续搜索返回的种子。 除非我阻止并等待结果,然后手动将其添加。
更新2 为了进一步说明,我试图防止在
future.get
上发生阻塞,因此我可以将返回的结果添加为它们 排定为任务。
int MaxThreads = 3;
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(MaxThreads); // How many threads
List<Future<String>> resultList = new ArrayList<>();// Create results list
for (int i = 0; i < 10; i ++) {
SpawnThread task = new SpawnThread("example.com");// Create Tasks
Future<String> result = executor.submit(task);//Launch tasks
//System.out.println("Added " + CurrentNum + " to the que!");
resultList.add(result);//Store Task Result
}
for(Future<String> future : resultList) //Loop through results
{
String resultfinished;
try {
resultfinished = future.get();
System.out.println(resultfinished);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
executor.shutdown();
我认为我需要的是一个非阻塞队列,其结果可以 重新添加到提供新域进行爬网的列表中,但是 我似乎无法使其正常工作。
BlockingQueue queue = new ArrayBlockingQueue(1024);
Executor executor = Executors.newFixedThreadPool(4);
CompletionService<List<String>> completionService =
new ExecutorCompletionService<List<String>>(executor);
List<String> pagesToVisit = new ArrayList<String>();
Set<String> pagesVisited = new HashSet<String>();
String SeedPage = "https://example.com/";
String currentURL = null;
boolean done = false;
while(!done) {
int listsize = pagesToVisit.size();
if(pagesToVisit.isEmpty())
{
currentURL = SeedPage;
pagesVisited.add(SeedPage);
listsize = pagesToVisit.size() + 1;
}
else
{
currentURL = nextUrl();
}
for(int k = 0; k < listsize; k ++)
{
completionService.submit(new Spider(currentURL,"IP","PORT" ) {
});
}
int received = 0;
boolean errors = false;
while(received < listsize && !errors)
{
Thread.sleep(1000);
Future<List<String>> resultFuture = completionService.take(); //blocks if none available
try
{
List<String> result = resultFuture.get();
pagesToVisit.addAll(result);
received ++;
}
catch(Exception e)
{
//log
e.printStackTrace();
errors = true;
}
}
}
答案 0 :(得分:0)
我不确定我是否让你问对了,但是
您可以使用awaitTermination();
方法
布尔布尔awaitTermination(长时间超时, TimeUnit单位) 抛出InterruptedException
阻塞,直到关闭后所有任务完成执行 请求,或者发生超时,或者当前线程被中断, 以先发生的为准。
参数:timeout-等待的最大时间单位-的时间单位 超时参数
返回值:如果该执行程序终止,则返回true;如果超时,则返回false 终止前已过去
抛出:InterruptedException-如果在等待时被中断
例如
try{
executor.awaitTermination(5, TimeUnit.Seconds);
}catch(InterruptedException e)
{
// Catch block
}
shutdown()方法不等待线程完成
启动有序关闭,在该关闭中执行先前提交的任务,但不接受任何新任务。如果已关闭,则调用不会产生任何其他影响。 此方法不等待先前提交的任务完成执行。