当前位置: 首页 > 知识库问答 >
问题:

在Java Future上使用带有isDone和Cancel的轮询,而不是阻塞get

荣德厚
2023-03-14

我正在处理一些我不能立即重构的遗留代码。

代码使用阻塞Java未来。它使用future.get(with TimeOut,...)。这意味着我们需要有一个合适大小的线程池来进行足够的响应。因为调用将被阻塞,直到它们完成或超时。

问:我在考虑获取未来并将其放入一个数据结构中,该结构将知道任务的执行开始。然后有一个专用线程或池,它将在数据结构上循环并检查是否future.isDone或已超过超时限制。如果是,它可以获取结果或取消执行。这样就不需要太多线程了。这是一个正确的实现还是根本不推荐

提前致谢。

编辑:

只是为了提供更多的背景。这些线程用于记录下游服务。我们真的不关心反应,但我们不想联系到洪。因此,我们需要抓住未来,确保它被取消或超时。

这是我在提出问题后写的一个基本模拟。

@Component
public class PollingService {

    private ExecutorService executorService = Executors.newFixedThreadPool(1);
    PoorMultiplexer poorMultiplexer = new PoorMultiplexer();
    private ConcurrentMap<Integer, Map<Future, Long>> futures = new ConcurrentHashMap<>();

    public void startHandler(){
        Thread handler = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        //This should be handled better. If there is not anything stop and re-start it later.
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for(Iterator<ConcurrentMap.Entry<Integer, Map<Future, Long>>> it = futures.entrySet().iterator(); it.hasNext();){
                        ConcurrentMap.Entry<Integer, Map<Future, Long>> entry = it.next();
                        Map<Future, Long> futureMap = entry.getValue();
                        boolean isProcessed = false;
                        if(futureMap.keySet().iterator().next().isDone()){
                            //mark completed
                            isProcessed = true;
                        }

                        if(futureMap.values().iterator().next() < (300 + System.currentTimeMillis()) && !isProcessed){
                            //cancel
                            futureMap.keySet().iterator().next().cancel(true);
                            isProcessed = true;
                        }

                        if(isProcessed){
                            futures.remove(entry.getKey());
                            System.out.println("Completed : " + entry.getKey());
                        }

                    }

                    System.out.println("Run completed");
                }
            }
        });

        handler.start();
    }

    public void run(int i) throws InterruptedException, ExecutionException{
        System.out.println("Starting : " + i);

        poorMultiplexer.send(new Runnable() {
            @Override
            public void run() {
                long startTime = System.currentTimeMillis();
                Future future = poorMultiplexer.send(execute());

                Map<Future, Long> entry = new HashMap<>();
                entry.put(future, startTime);
                futures.put(i, entry);
                System.out.println("Added : " + i);
            }
        });
    }

    public void stop(){
        executorService.shutdown();
    }

    public Runnable execute(){
        Worker worker = new Worker();
        return worker;
    }
}


//This is a placeholder for a framework
class PoorMultiplexer {
    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    public Future send(Runnable task){
        return executorService.submit(task);
    }
}


class Worker implements Runnable{

    @Override
    public void run() {
        //service call here
    }

}

共有1个答案

倪灿
2023-03-14

在我看来,使用单独的线程异步轮询一组未来确实是一个合理的实现。也就是说,如果您能够添加库依赖项,您可能会发现切换到Guava的ListenableFuture更容易,因为Guava为异步工作提供了大量实用工具。

 类似资料:
  • 我是socket.io的新手,已经用node/express/socket.io编写了我的第一个应用程序。我想向公众发布我的应用程序,但我担心它对很多人都不起作用。我有几个朋友测试了我的应用程序,一切都很顺利(这是一个非常简单的应用程序)。我担心的是:现在每个连接似乎都在使用websockets,这正是我想要的。但是,我的应用程序有时会因为客户端的一些奇怪的事情而降级为“投票”吗?如果是,sock

  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 我有一个顶点,它有一个处理程序,可以在事件循环线程中调用Vertx的Web客户端。实际的底层API调用是同步的还是异步的?它会阻塞我的事件循环线程吗?假设我的API调用需要30秒才能返回。 我是否需要用Vertx.execute阻塞(p-

  • 正在寻找将Flux转换为<code>列表 使用反应式编程,但graph ql期望

  • 问题内容: Redis非常快。在我的机器上,大多数情况下它的速度与node.js中的本机Javascript语句或函数调用一样快。在node.js中编写常规的Javascript代码很容易/很轻松,因为不需要回调。我不明白为什么使用node.js在Redis中获取/设置键/值数据不那么容易。 假设node.js和Redis在同一台机器上,是否有任何npm库允许使用阻塞调用与node.js上的Red

  • 试图将axios post请求从Vue应用程序(localhost)发送到我的nodejs API(localhost和heroku)。 如果请求是在没有数据或头的情况下发送的,则接收响应不会有问题,但是当我添加它们时,我会收到以下错误: 我已经尝试了不同的选择,服务器端和客户端,建议类似的问题,但没有成功。 客户端请求: 服务器endpoint: 我尝试了一些答案: 对预飞行请求的响应没有通过访