[英]How to perform short-circuit evaluation in Java on two parallel threads that return boolean values?
我正在寻找逻辑上等同于以下问题的指导:
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
}
上述结构给出了正确的结果, 但是即使从taskB完成后结果已知,总是等待taskA完成 。
有没有更好的结构,如果任何一个线程返回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();
}
这是使用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);
}
}
感谢@Lav指出了ExecutorCompleteionService
类。
我认为监视器逻辑在这种情况下可能会很好地工作,但它取决于您是否能够添加更改callables来接收引用。 它可能在parallelOR()方法中看起来像这样:
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();
}
在您的callables中call()方法结束时,您将拥有:
synchronized(monitor){
monitor.notify();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.