如何在 java 中导致超时异常时获取 Future return
how to get Future return when cause timeout Exception in java
我想知道在使用 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)时,可以得到我期望的值"world"。
现在我想得到 return 值是 "hello",当我使用 future.get(2, TimeUnit.SECONDS) .
我该怎么做?谢谢
不,执行过程中不会抛出该异常。而是抛出 InterruptedException。 (在那里尝试 System.out.println)。
控制流程:
- 执行超时
- 线程被中断
- 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。
在每个循环步骤中存储进度时,这也是一个陷阱。赶上超时后,进度可能仍会更新。
我想知道在使用 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)时,可以得到我期望的值"world"。 现在我想得到 return 值是 "hello",当我使用 future.get(2, TimeUnit.SECONDS) .
我该怎么做?谢谢
不,执行过程中不会抛出该异常。而是抛出 InterruptedException。 (在那里尝试 System.out.println)。
控制流程:
- 执行超时
- 线程被中断
- 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。
在每个循环步骤中存储进度时,这也是一个陷阱。赶上超时后,进度可能仍会更新。