Java 当未来任务的一个任务满足条件时,终止运行中的其他未来任务
使用Java8 我正在尝试编写一个程序,从diff服务器下载日志文件,并在这些日志文件中搜索给定的文本。我现在做的是同步的。我想并行地完成它,并发现它可以使用java中的Future来完成。我正在使用apache.commons.io从URL下载文件。 下面是代码片段:Java 当未来任务的一个任务满足条件时,终止运行中的其他未来任务,java,multithreading,future,Java,Multithreading,Future,使用Java8 我正在尝试编写一个程序,从diff服务器下载日志文件,并在这些日志文件中搜索给定的文本。我现在做的是同步的。我想并行地完成它,并发现它可以使用java中的Future来完成。我正在使用apache.commons.io从URL下载文件。 下面是代码片段: ExecutorService executorService = Executors.newCachedThreadPool(); List<Future<XCluster>> clusterF
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<XCluster>> clusterFutures = new ArrayList<>();
for(XCluster cluster: clusters) {
clusterFutures.add(executorService.submit(() -> {
return downloadAndSearch(textToSearch, cluster);
}));
}
//For now I'm not doing anything with returned value from Future
ExecutorService ExecutorService=Executors.newCachedThreadPool();
List clusterFutures=new ArrayList();
用于(XCluster群集:群集){
clusterFutures.add(executorService.submit)(()->{
返回下载和搜索(textToSearch,群集);
}));
}
//现在我不做任何从未来返回值的事情
但现在我想终止在Future下启动的其他下载搜索操作,因为给定的搜索预期只能在其中一个服务器中找到。因此,没有必要继续我开始的其他未来任务。有谁能建议一种方法来做到这一点吗?我使用的是Java8,也欢迎使用其他选项。提前谢谢 ExecutorService有一个Shutdownow方法,该方法将停止所有线程并关闭服务 编辑: 我用Shutdownow做了一些实验,我发现它不能像我想的那样停止线程。AFAIK使用interrupts(),但并非所有线程都对中断做出反应 因此,我能想到的最佳选择是: 首先,创建一个指标类:
public static class Indicator{
private boolean isReady = false;
public void ready(){
isReady = true;
}
public boolean isReady(){
return isReady;
}
}
启动的线程应该共享一个指示符实例进行通信。
因此,您可以创建一个如下所示的可调用函数:
public static class Processor implements Callable<Integer> {
private volatile Indicator indicator;
private Integer number;
public Processor(Integer integer, Indicator isReady){
this.number = integer;
this.indicator = isReady;
}
@Override
public Integer call() throws Exception {
System.out.println("Thread started:" + Thread.currentThread().getId());
int counter = 0;
while (!indicator.isReady &&counter < number) {
// Make complicated things
Math.sin(counter);
counter++;
}
if(indicator.isReady){
//another thread finished
//delete resources
System.out.println("Thread interrupted: " + Thread.currentThread().getId() + " " + counter);
return -1;
} else {
System.out.println("Thread finished: " + Thread.currentThread().getId() + " " + counter);
indicator.ready();
return counter;
}
}
}
旁注:引用的类不必是静态的内部类,只需在一个文件中进行实验就更容易了。就代码而言,最简单的解决方案是使用一个关闭线程来取消所有未来:
final ExecutorService executorService = Executors.newCachedThreadPool();
final ExecutorService shutdownService = Executors.newSingleThreadExecutor();
List<Future<XCluster>> clusterFutures = new ArrayList<>();
for(XCluster cluster: clusters) {
clusterFutures.add(executorService.submit(() -> {
boolean cancelOthers = false;
try {
XCluster result = downloadAndSearch(textToSearch, cluster);
cancelOthers = yourPredicateOfSuccess();
return result;
} finally {
if (cancelOthers) {
shutdownService.execute(() -> {
executorService.shutdownNow();
});
}
}
}));
}
final ExecutorService ExecutorService=Executors.newCachedThreadPool();
final ExecutorService shutdownService=Executors.newSingleThreadExecutor();
List clusterFutures=new ArrayList();
用于(XCluster群集:群集){
clusterFutures.add(executorService.submit)(()->{
布尔值=false;
试一试{
XCluster结果=下载和搜索(textToSearch,群集);
cancelOthers=yourPredicateOfsSuccess();
返回结果;
}最后{
如果(取消其他){
shutdownService.execute(()->{
executorService.shutdownNow();
});
}
}
}));
}
另一个线程和try finally非常重要,因为这可以确保您不会取消几乎成功的方法运行。谢谢,还有一点。有没有一种方法可以让像finally这样的代码块在我关闭其他线程时执行。我需要清理其他futures下载的文件。谢谢,我尝试了这种方法,关闭了其他futures,但它不起作用。即使在调用shutdownNow()之后,线程仍继续执行
Thread started:11
Thread started:12
Thread finished: 11 100
Thread interrupted: 12 1001
Thread started:13
Thread interrupted: 13 0
final ExecutorService executorService = Executors.newCachedThreadPool();
final ExecutorService shutdownService = Executors.newSingleThreadExecutor();
List<Future<XCluster>> clusterFutures = new ArrayList<>();
for(XCluster cluster: clusters) {
clusterFutures.add(executorService.submit(() -> {
boolean cancelOthers = false;
try {
XCluster result = downloadAndSearch(textToSearch, cluster);
cancelOthers = yourPredicateOfSuccess();
return result;
} finally {
if (cancelOthers) {
shutdownService.execute(() -> {
executorService.shutdownNow();
});
}
}
}));
}