Java 当未来任务的一个任务满足条件时,终止运行中的其他未来任务

Java 当未来任务的一个任务满足条件时,终止运行中的其他未来任务,java,multithreading,future,Java,Multithreading,Future,使用Java8 我正在尝试编写一个程序,从diff服务器下载日志文件,并在这些日志文件中搜索给定的文本。我现在做的是同步的。我想并行地完成它,并发现它可以使用java中的Future来完成。我正在使用apache.commons.io从URL下载文件。 下面是代码片段: ExecutorService executorService = Executors.newCachedThreadPool(); List<Future<XCluster>> clusterF

使用Java8

我正在尝试编写一个程序,从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
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();
                });
              }
            }
        }));
    }