Java中导致超时异常时如何获取Future返回 [英] how to get Future return when cause timeout Exception in java

查看:84
本文介绍了Java中导致超时异常时如何获取Future返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm wondering can I get the result when it cause timeout Exception when use Future and ExecutorService, for example, below is my code

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)时,可以按预期获得值世界".现在,当我使用future.get(2,TimeUnit.SECONDS)时,我想要返回的值是"hello".

when I use future.get(5, TimeUnit.SECONDS), It's OK to get value "world" as I expect. now I want get the return value is "hello", when I use future.get(2, TimeUnit.SECONDS) .

我该怎么做?谢谢

推荐答案

不,该异常不会在执行过程中抛出.而是抛出一个 InterruptedException .(在那里尝试使用System.out.println).

No, that exception is not thrown inside the execution. Instead a InterruptedException is thrown. (Try a System.out.println there).

控制流程:

  1. 执行中发生超时

    1. 线程被中断

  • 3a.抛出TimeoutException
  • 3b.FutureTask收到InterruptedException
  • 当3a和3b在两个线程中(异步)发生时,顺序可能是3b; 3a.但是3a; 3b似乎是自然顺序.

    As 3a and 3b happen in two threads (asynchroneously) the order could be 3b;3a. However 3a;3b seems the natural order.

    这样做:

        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线程不能保证已关闭(因为可能没有捕获,即使捕获之后代码仍会继续).

    Notice: I think the FutureTask thread is not guaranteed to have shutdown (as there might not have been a catch, and even then after the catch the code continues).

    将catch InterruptedException捕获到某个地方存放结果将失败,因为在捕获TimeoutException时,FutureTask仍然不能具有InterruptedException.

    Using catch InterruptedException to somewhere deposit a result, will fail, as at the moment of catching the TimeoutException the FutureTask still can have no InterruptedException.

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

    This is also a pitfall when storing a progress in every loop step. After catching the timeout the progress might still be updated.

    这篇关于Java中导致超时异常时如何获取Future返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆