java - Executors.newFixedThreadPool 如何停止同步方法上的所有活动线程
问题描述
我有一个执行器服务,它同时提交 x 数量的线程来执行一项长任务。我需要能够停止所有当前正在运行的线程并阻止排队的任务启动。我正在尝试实现一种方法来处理正在等待同步方法的停止线程,在该同步方法中,runnable 将字符串列表传递回调用它的接口。
@Override
public synchronized void FilterResults(List<String> Results) {
//System.out.println("Result found: " + Results.size());
try {
Set<String> hs = new HashSet<>();
hs.addAll(Results);
Results.clear();
Results.addAll(hs);
for (String tempURL : Results) {
//System.out.println("Found url: " + tempURL);
if (!isCompleted(tempURL) && !isQueued(tempURL) && !isRunning(tempURL)) {
System.out.println("Added: " + tempURL + " to queue.");
queueLink(tempURL);
startNewThread(tempURL);
}
}
}catch(Exception e) {
}
return;
}
private synchronized void startNewThread(String seedURL) {
if (!isCompleted(seedURL) && !isRunning(seedURL) ) {
if (completedSize("") + runningSize() > 99) {
Stop();
}
String tempProxy = "";
String tempPort = "";
if (UseProxies) {
String Proxy = grabFreeProxy();
String[] splitProxy = Proxy.split(":");
tempProxy = splitProxy[0]; // 004
tempPort = splitProxy[1]; // 034556
}
//System.out.println("Proxy: " + tempProxy);
//System.out.println("Port: " + tempPort);
execService.submit(new Crawl(seedURL, this, tempProxy, tempPort, UseProxies));
removeFromQueue(url);
}
}
@Override
public Collection<String> Stop() {
try {
execService.shutdown();
if (execService.awaitTermination(45, TimeUnit.SECONDS)) {
System.out.println("task completed");
} else {
execService.shutdownNow();
}
} catch (InterruptedException e) {
}
return PROFILES;
}
The Runnable
public class Crawl implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted() && shutdown == false) {
try {
//System.out.println(crawler.queueSize());
Thread.sleep(100);
Crawl(url);
}catch (InterruptedException e) {
Thread.currentThread().interrupt(); // set interrupt flag
}
}
public void crawl(){
try {
submitResults(urls); //Calls FilterResults()
} catch (InterruptedException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
Thread.currentThread().interrupt();
}
crawler.removeUsedProxy(Proxy + ":" + Port);
this.shutdown();
}
}
当我调用我的关闭方法时,它需要 45 秒 + 是否有可靠地取消任务而无需长时间等待?这个数字随着我有更多线程而增长,并且由于所有线程都在阻塞等待提交结果,因此可能需要一些时间。如果我手动取消任务,我不在乎是否存储了结果,我只需要能够取消即可。有任何想法吗?
更新我试过了
ExecutorService#shutdownNow
。在杀死仍然被该方法阻塞的任务时,它并不可靠synchronized
。
解决方案
看起来您需要使用ExecutorService#shutdownNow
以防您不想等待并完成所有工作,并且您将收到一个包含未执行任务的列表。ExecutionService#awaitTermination
如果您想要/需要提供时间来等待任务完成,您可以使用(与 45 秒不同的参数)。
推荐阅读
- javascript - 如何使用但在 javascript 中定向 html 页面?
- assembly - 引导加载程序在 qemu 中工作,但在 virtualbox 和硬件中失败
- javascript - 如何进行无限滚动?
- c - Azure IoT SDK - 检查设备是否已经注册
- codepen - 在 CodePen 中更新 Pen 的内容时,我的 Pen 的缩略图不会更新
- php - PHP DOM $xpath->query 获取原始 HTML 作为输出
- azure - 如何使用 Cypress.io 使用 MS Active Directory 登录?
- flutter - Flutter如何在任意孩子上使用boxShadow?
- php - 将 Excel 字符串转换为 php 可读字符串
- qt - 必需的属性不适用于中继器