import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class ThreeThread { public static void main(String[] args) { //工作线程 Worker worker = new Worker(); //使用 FutrueTask 包装 Callable 对象 FutureTask<Integer> ft = new FutureTask<>(worker); for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + "循环变量i的值:" + i); if (i == 5) { new Thread(ft, "有返回值的线程").start(); } try { //获取线程返回值 System.out.println("子线程的返回值:" + ft.get()); } catch (Exception e) { e.printStackTrace(); } } } //创建 Callable 接口的实现类 public static class Worker implements Callable<Integer> { // Class 'Worker' must either be declared abstract or implement abstract method 'call()' in 'Callable' @Override public Integer call() throws Exception { int t = 0; for (; t < 10; t++) { System.out.println(Thread.currentThread().getName() + "循环变量t的值:" + t); } return t; } } }代码只打印了 main循环变量i的值:0
时间: 2024-03-18 20:43:28 浏览: 41
这段代码只输出了主线程循环变量 i 的值 0,原因是在主线程中,当 i 的值等于 5 时,新启动了一个子线程来执行 FutureTask,但是在主线程中立即通过 ft.get() 方法获取了子线程的返回值,此时主线程会一直阻塞等待子线程的返回值,并且子线程也还没有机会执行。因此,程序只输出了主线程循环变量 i 的值 0,而没有输出子线程的任何信息。要解决这个问题,可以将获取子线程返回值的代码放到 for 循环外面,等待子线程执行完毕再获取其返回值。
相关问题
java.util.concurrent.ExecutionException: java.lang.reflect.InvocationTargetException
在Java中,`java.util.concurrent.ExecutionException` 和 `java.lang.reflect.InvocationTargetException` 都是异常类型,通常出现在异步编程场景下,特别是处理并发任务的结果时。
`ExecutionException` 是由`Future` 或 `ExecutorService` 类型的 `FutureTask` 的 `get()` 或 `get(long timeout, TimeUnit unit)` 方法抛出的。当你通过这些方法获取一个异步计算结果(例如 `Thread`, `Callable`, 或 `Runnable`)时,如果这个计算过程中抛出了异常,`ExecutionException` 就会被封装并抛出,让你能够捕获到原始的运行时错误。
`InvocationTargetException` 则是在反射API(如 `java.lang.reflect.Method.invoke()`)调用一个方法时发生的。它通常发生在尝试调用的方法自身抛出了异常的情况下。当你使用反射来执行动态方法调用时,如果目标方法内部有异常,`InvocationTargetException` 将包裹该异常,并由外部代码处理。
结合这两个异常,如果你在使用并发库处理任务时遇到了它们,可能是异步操作失败或方法调用出现了预期之外的问题。解决这类问题需要检查异常的内容,并采取适当的错误处理措施。
java.util.concurrent.ExecutionException:Boxed Error
在Java中,`java.util.concurrent.ExecutionException`是一个典型的运行时异常,它由`FutureTask`或`ExecutorService`的`get()`或`await()`等方法抛出。这些方法会在阻塞等待异步任务完成时抛出此异常,如果任务的结果不是直接可用的(例如,任务本身是一个耗时的操作,或者包含一个`Callable`而不是`Runnable`),那么结果可能会被封装在一个`Future`对象中。
当你尝试从`Future`中获取结果,而该结果实际上是`ExecutionException`(即,某个底层操作失败导致的Error)时,`ExecutionException`就会作为这个包装异常抛出。这种设计是为了让你能够捕获并处理任务执行过程中的异常,而不是仅仅让整个程序因为底层错误而终止。
例子上,如果你编写了这样的代码:
```java
Future<String> future = executor.submit(myCallable);
try {
String result = future.get(); // 这里会抛出 ExecutionException 如果myCallable抛出异常
} catch (ExecutionException e) {
if (e.getCause() instanceof BoxedError) { // 检查是否为Boxed Error类型
handleSystemLevelError((BoxedError) e.getCause());
} else {
handleRegularException(e.getCause());
}
}
```
阅读全文