如何在原因超时时返回Future返回java中的异常

时间:2018-01-05 08:15:53

标签: java future executorservice

我想知道可以在导致超时时获得结果使用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)时。

我该怎么做?感谢

1 个答案:

答案 0 :(得分: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。

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