使用java 8
我正在尝试编写一个prog来从diff服务器下载日志文件,并在这些日志文件中搜索给定的文本。我正在做同步现在。我想并行执行它并发现它可以使用Java中的Future来完成。我正在使用apache.commons.io从URL下载文件。 这是代码片段:
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
但是现在我想终止在Future下启动的其他下载搜索操作,因为预期只能在其中一个服务器中找到给定的搜索。所以没有必要继续我开始的其他Future任务。任何人都可以建议这样做的方法吗?我正在使用java 8,也欢迎其他选项。在此先感谢!
答案 0 :(得分:1)
ExecutorService有一个shutdownNow方法,它将停止所有线程并关闭服务。
修改强>
我用shutDownNow进行了一些实验,因为我认为它不能像我想的那样停止线程。 AFAIK它使用中断()但并非所有线程都对中断做出反应。
所以我能提出最好的选择:
首先,创建一个指标类:
public static class Indicator{
private boolean isReady = false;
public void ready(){
isReady = true;
}
public boolean isReady(){
return isReady;
}
}
您启动的线程应共享一个Indicator实例进行通信。 所以你可以像这样创建一个Callable:
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;
}
}
}
这样,当第一个线程准备就绪时,它可以阻止其他线程,并且它们会在自己清理后进行清理。
我尝试了如下:
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<Integer>> clusterFutures = new ArrayList<>();
Indicator indicator = new Indicator();
clusterFutures.add(executorService.submit(new Processor(100, indicator)));
clusterFutures.add(executorService.submit(new Processor(10000, indicator)));
clusterFutures.add(executorService.submit(new Processor(10000000,indicator)));
}
示例输出:
Thread started:11
Thread started:12
Thread finished: 11 100
Thread interrupted: 12 1001
Thread started:13
Thread interrupted: 13 0
旁注:引用的类不必是静态内部类,只是在一个文件中进行实验更容易。
答案 1 :(得分: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();
});
}
}
}));
}
另一个线程和try-finally非常重要,因为这可以确保您不会取消几乎成功的方法运行。