如何从多个线程中获取第一个结果并取消剩余的结果

2024-03-13

我有请求并且多线程, 哪个是寻找结果以不同的方式,每个线程应该在某个时刻得到一些结果..我需要采取从第一个结果完成的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(使用前将#替换为@)

如何从多个线程中获取第一个结果并取消剩余的结果 的相关文章

随机推荐