[英]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.