Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中对返回布尔值的两个并行线程执行短路计算?_Java_Threadpool_Lazy Evaluation_Java.util.concurrent_Short Circuiting - Fatal编程技术网

如何在Java中对返回布尔值的两个并行线程执行短路计算?

如何在Java中对返回布尔值的两个并行线程执行短路计算?,java,threadpool,lazy-evaluation,java.util.concurrent,short-circuiting,Java,Threadpool,Lazy Evaluation,Java.util.concurrent,Short Circuiting,我正在寻找逻辑上等同于以下问题的指导: public boolean parallelOR() { ExecutorService executor = Executors.newFixedThreadPool(2); Future<Boolean> taskA = executor.submit( new SlowTaskA() ); Future<Boolean> taskB = executor.submit( new SlowTaskB()

我正在寻找逻辑上等同于以下问题的指导:

public boolean parallelOR() {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    Future<Boolean> taskA = executor.submit( new SlowTaskA() );
    Future<Boolean> taskB = executor.submit( new SlowTaskB() );

    return taskA.get() || taskB.get(); // This is not what I want
    // Exception handling omitted for clarity
 }
公共布尔并行器(){
ExecutorService executor=Executors.newFixedThreadPool(2);
Future taskA=executor.submit(新的SlowTaskA());
Future taskB=executor.submit(新的SlowTaskB());
return taskA.get()| taskB.get();//这不是我想要的
//为清楚起见,省略了异常处理
}
上述构造给出了正确的结果,但始终等待taskA完成 即使由于taskB已完成,结果已为人所知

是否有更好的构造允许返回值 如果其中一个线程在不等待第二个线程完成的情况下返回true


(涉及的平台是Android,如果这会影响结果)。

尝试使用ExecutorCompletionService。。。差不多

    ExecutorService pool = Executors.newFixedThreadPool(2);
    ExecutorCompletionService<Result> completionService = new ExecutorCompletionService<Result>(pool);
completionService.submit(new SlowTaskA());
completionService.submit(new SlowTaskB());
    Future<Result> future;
            try {
                future = completionService.take();
                Result currentResult=null;
                try {
                    currentResult = future.get();
                } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                // got the 1st result in obj currentResult, return true or obj
                return true;
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
ExecutorService池=Executors.newFixedThreadPool(2);
ExecutorCompletionService completionService=新的ExecutorCompletionService(池);
completionService.submit(新的SlowTaskA());
completionService.submit(新SlowTaskB());
未来;
试一试{
future=completionService.take();
结果currentResult=null;
试一试{
currentResult=future.get();
}捕获(执行例外){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
//在obj currentResult中获得第一个结果,返回true或obj
返回true;
}捕捉(中断异常e1){
e1.printStackTrace();
}

下面是一个使用
ExecutorCompletionService
的ParallelOr实现。它等待任务,直到返回
true
。如果没有,它最终返回
false

public class ParallelOr {

    static class LongTask implements Callable<Boolean> {

        private int milliseconds;
        private boolean val;

        public LongTask(int milliseconds, boolean val) {
            this.milliseconds = milliseconds;
            this.val = val;
        }

        @Override
        public Boolean call() throws Exception {
            try {
                Thread.sleep(milliseconds);
            } catch(Exception ex) {}
            return val;
        }
    }

    static boolean ParallelOr(List<Callable<Boolean>> tasks) {
        ExecutorService pool = Executors.newFixedThreadPool(tasks.size());
        ExecutorCompletionService<Boolean> completionService
                = new ExecutorCompletionService<Boolean>(pool);

        for(Callable<Boolean> task : tasks) {
            completionService.submit(task);
        }

        for(int i = 0; i < tasks.size(); i++) {
            try {
                Future<Boolean> result = completionService.take();
                if(result.get()) {
                    return true;
                }
            } catch (InterruptedException e) {
            } catch (ExecutionException e) {}
        }

        return false;
    }


    public static void main(String[] args) {
        ArrayList<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();

        tasks.add(new LongTask(1000, true));
        tasks.add(new LongTask(500, false));
        tasks.add(new LongTask(6000, false));

        boolean result = ParallelOr(tasks);

        System.out.println(result);
    }
}
公共类并行器{
静态类LongTask实现了可调用{
私有整数毫秒;
私有布尔值;
公共长任务(整数毫秒,布尔值){
this.millizes=毫秒;
this.val=val;
}
@凌驾
公共布尔调用()引发异常{
试一试{
睡眠(毫秒);
}捕获(例外情况除外){}
返回val;
}
}
静态布尔并行器(列出任务){
ExecutorService池=Executors.newFixedThreadPool(tasks.size());
ExecutorCompletionService完成服务
=新的ExecutorCompletionService(池);
for(可调用任务:任务){
completionService.submit(任务);
}
对于(int i=0;i

感谢@Lav指出了
executorcompleteinservice
类。

我认为监视器逻辑在这种情况下可能会很好地工作,尽管它取决于您是否能够添加或更改可调用项以接收引用。在parallelOR()方法中,它可能如下所示:


你能修改任务吗?所以你不想等到线程A和线程B完成后再获取值???当A完成后,你会得到值,反之亦然?这个想法似乎是,如果taskB先完成,并且是真的,然后你可以短路,而不是等待taskA完成。也许你可以让先完成的任务中断另一个任务?我愿意使用不同的同步原语-但我认为我必须让任务完成,因为它们使用的资源,即使在一个任务返回true后,第二个任务的结果也不再令人感兴趣。+1-酷!我以前从未遇到过
ExecutorCompletionService
。也许这是它的设置方式所固有的,但是如果您是从任务内部发送信号,您如何确保
isDone()
将返回
true
?我有点不确定您在这里的意思。我将把这个块放在call()方法的末尾,这样您就可以明确地知道可调用对象已经完成了处理。
ExecutorService executor = Executors.newFixedThreadPool(2);
    final Object monitor = new Object();
    Future<Boolean> taskA = executor.submit( new SlowTaskA(monitor) );
    Future<Boolean> taskB = executor.submit( new SlowTaskB(monitor) );
    Boolean ret = null,;
    try {
        loop:while(true){
            synchronized(monitor){
                monitor.wait();
            }
            if(taskA.isDone()){
                ret = taskA.get();
                if(ret.booleanValue()){
                    taskB.cancel(true); // If you can.
                    break loop;
                }
            }
            if(taskB.isDone()){
                ret = taskB.get();
                if(ret.booleanValue()){
                    taskA.cancel(true);
                    break loop;
                }
            }
            // Ifs in case of spurious wake-up
        }           
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
synchronized(monitor){
            monitor.notify();
        }