【问题标题】:how to get Future return when cause timeout Exception in javajava - 在java中导致超时异常时如何获得Future返回
【发布时间】:2018-01-05 08:15:53
【问题描述】:

我想知道当使用Future和ExecutorService导致超时异常时我能得到结果吗,例如,下面是我的代码

package com.example;

import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.junit.Test;

public class FutureTest {
    public static String sayHello() {
        try {
            Thread.sleep(3000);
            return "world";
        } catch (Exception e) {
            return "hello";
        }
    }

    @Test
    public void testTimeoutAndInterrupt() throws Exception {
        ExecutorService executorService = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2, 0,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>(10), new BasicThreadFactory.Builder().namingPattern(
            "executor-pool-%d").daemon(true).build());

        String processName = UUID.randomUUID().toString();

        Future<String> future = executorService.submit(
            () -> {
                return sayHello();
            }
        );
        try {
            String result = future.get(2, TimeUnit.SECONDS);
            System.out.println("future result:" + result);
        } catch (TimeoutException e) {
            System.out.println("timeout exception");
        } finally {
            future.cancel(true);
            System.out.println("cancel by future");
        }
    }
}

当我使用future.get(5, TimeUnit.SECONDS) 时,可以按照我的预期获得价值“世界”。 现在我想得到返回值为“hello”,当我使用 future.get(2, TimeUnit.SECONDS) 时。

我该怎么做?谢谢

【问题讨论】:

    标签: java future executorservice


    【解决方案1】:

    不,该异常不会在执行过程中引发。而是抛出 InterruptedException。 (在那里尝试 System.out.println)。

    控制流程:

      1. 执行中发生超时
      1. 线程被中断
    • 3a。抛出 TimeoutException
    • 3b。 FutureTask 得到一个 InterruptedException

    由于 3a 和 3b 发生在两个线程中(异步),因此顺序可能是 3b;3a。然而 3a;3b 似乎是自然顺序。

    这样做:

        String result;
        try {
            result = future.get(2, TimeUnit.SECONDS);
            System.out.println("future result:" + result);
        } catch (TimeoutException e) {
            System.out.println("timeout exception");
            result = "hello";
        } finally {
    

    注意:我认为 FutureTask 线程不能保证已关闭(因为可能没有捕获,即使捕获后代码仍在继续)。

    使用 catch InterruptedException 到某处存放结果,会失败,因为在捕获 TimeoutException 的那一刻,FutureTask 仍然可以没有 InterruptedException。

    在每个循环步骤中存储进度时,这也是一个陷阱。赶上超时后,进度可能仍会更新。

    【讨论】:

    猜你喜欢
    • 2021-02-03
    • 1970-01-01
    • 2018-05-19
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    相关资源
    最近更新 更多