我有请求并且多线程, 哪个是寻找结果以不同的方式,每个线程应该在某个时刻得到一些结果..我需要采取从第一个结果完成的thread,返回这个结果并且kill全部剩余线程。当我返回一些默认结果时,我也会超时。
我可以想到两种解决方案,但对我来说,没有一个是“正确的”。
1)循环遍历任务,询问它们是否完成,休眠一段时间并返回它找到的第一个完成的任务。
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.log4j.LogManager;
public class App {
public static final ExecutorService executors = Executors.newCachedThreadPool();
public static void main(String[] args) {
ArrayList<Future<String>> taskList = new ArrayList<>();
taskList.add(executors.submit(new Task1()));
taskList.add(executors.submit(new Task2()));
String result = null;
long start = System.currentTimeMillis();
long timeout = 1000;
while ((start + timeout) < System.currentTimeMillis()) {
try {
for (Future<String> future : taskList) {
if (future.isDone()) {
result = future.get();
break;
}
}
if (result != null) {
break;
}
Thread.sleep(10);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
if (result == null) {
result = "default..";
}
}
}
class Task1 implements Callable<String> {
@Override
public String call() throws Exception {
// find result in one way
return new String("result..");
}
}
class Task2 implements Callable<String> {
@Override
public String call() throws Exception {
// find result in some other way
return new String("result..");
}
}
2)通过调用使用另一个线程监视每个任务future.get(timeout, TimeUnit.MILLISECONDS);
然后第一个完成的线程将调用future.cancel(true);
对于所有其他线程...
在我看来,第一个解决方案就像浪费处理器时间,而第二个解决方案在我看来就像浪费线程。
最后,Question是:还有更好的解决办法吗?
先感谢您
Edit:谢谢大家的回答,我已经使用“John H”的回答解决了这个问题:
有一个内置函数可以执行此操作:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAny%28java.util.Collection,%20long,%20java.util.concurrent.TimeUnit%29 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAny%28java.util.Collection,%20long,%20java.util.concurrent.TimeUnit%29
这将调用您分配给它的所有任务,并等待第一个任务在规定的时间内返回答案。如果它们都没有及时返回结果,您可以捕获 TimeoutException 并返回默认值。否则,您可以使用它返回的第一个值,它将负责取消其余任务。
有一个内置函数可以执行此操作:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAny%28java.util.Collection,%20long,%20java.util.concurrent.TimeUnit%29 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#invokeAny%28java.util.Collection,%20long,%20java.util.concurrent.TimeUnit%29
这将调用您分配给它的所有任务,并等待第一个任务在规定的时间内返回答案。如果它们都没有及时返回结果,您可以捕获 TimeoutException 并返回默认值。否则,您可以使用它返回的第一个值,它将负责取消其余任务。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)