如何在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();
}