深入解析 Java Future
类及代码示例
在 Java 并发编程中,Future
类是一个用于表示异步任务计算结果的接口。它为我们提供了获取异步执行任务的结果、检查任务状态、取消任务等功能。在实际开发中,Future
类常与 ExecutorService
配合使用,来管理并发任务的执行。本文将深入解析 Future
类的功能,并通过具体的代码示例帮助理解其用法。
Future
接口概述
Future
接口定义了与异步任务相关的多个方法,它用于获取任务执行结果、检查任务状态、取消任务等操作。
public interface Future<V> {
V get() throws InterruptedException, ExecutionException; // 阻塞获取结果
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; // 带超时的阻塞获取结果
boolean cancel(boolean mayInterruptIfRunning); // 取消任务
boolean isCancelled(); // 判断任务是否被取消
boolean isDone(); // 判断任务是否已完成
}
Future
方法详解
1. get()
方法
get()
是一个阻塞方法,用于获取异步任务的执行结果。如果任务已经完成,get()
会立即返回结果;如果任务还在执行,调用线程会被阻塞,直到任务完成并返回结果。该方法会抛出两个异常:
InterruptedException
:当当前线程在等待任务时被中断。ExecutionException
:当任务执行发生异常时,封装在ExecutionException
中。
V result = future.get(); // 阻塞获取任务结果
2. get(long timeout, TimeUnit unit)
方法
与 get()
类似,但是带有超时限制。如果任务在指定时间内没有完成,会抛出 TimeoutException
。如果任务超时,get()
方法会立即返回,且当前线程不再阻塞。
V result = future.get(5, TimeUnit.SECONDS); // 等待最多 5 秒
3. cancel(boolean mayInterruptIfRunning)
方法
该方法用于取消正在执行的任务。mayInterruptIfRunning
参数指定是否可以中断正在执行的任务:
- 如果为
true
,则可以中断任务。 - 如果为
false
,则任务在执行过程中无法被中断。
该方法返回一个布尔值:
- 如果任务已经完成或无法取消,返回
false
。 - 如果任务成功取消,返回
true
。
boolean cancelled = future.cancel(true); // 取消任务,并尝试中断
4. isCancelled()
方法
判断任务是否已被取消。如果任务已经开始执行并且无法取消,返回 false
;如果任务尚未执行且已经取消,返回 true
。
boolean isCancelled = future.isCancelled(); // 判断任务是否被取消
5. isDone()
方法
判断任务是否已经完成。无论任务是正常完成,还是由于异常或被取消,都会返回 true
。如果任务正在执行或尚未开始,返回 false
。
boolean isDone = future.isDone(); // 判断任务是否已完成
Future
类与 ExecutorService
的结合使用
Future
接口常与 ExecutorService
接口结合使用,ExecutorService
提供了多种方法来提交异步任务,其中最常用的 submit()
方法返回一个 Future
对象,允许获取任务的执行结果、判断任务的状态以及取消任务。
代码示例:ExecutorService
和 Future
基本用法
import java.util.concurrent.*;
public class FutureExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建一个固定线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 提交一个异步任务,返回 Future 对象
Future<Integer> future = executorService.submit(() -> {
System.out.println("Task started");
Thread.sleep(2000); // 模拟耗时任务
return 123;
});
// 等待任务执行完成,并获取结果
Integer result = future.get(); // 阻塞获取结果
System.out.println("Task result: " + result); // 输出任务的结果
executorService.shutdown(); // 关闭线程池
}
}
在这个例子中:
- 我们创建了一个固定大小为 2 的线程池。
- 提交了一个异步任务并返回
Future
对象。 - 使用
future.get()
方法等待任务完成并获取结果。
代码示例:带超时限制的 Future.get()
import java.util.concurrent.*;
public class TimeoutFutureExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 提交一个耗时任务
Future<Integer> future = executorService.submit(() -> {
Thread.sleep(3000); // 模拟一个耗时任务
return 123;
});
try {
// 获取结果,但最多等待 2 秒
Integer result = future.get(2, TimeUnit.SECONDS);
System.out.println("Task result: " + result);
} catch (TimeoutException e) {
System.out.println("Task timed out");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
在这个例子中:
- 任务会阻塞 3 秒,但
get(2, TimeUnit.SECONDS)
方法会等待最多 2 秒。 - 如果任务没有在 2 秒内完成,会抛出
TimeoutException
。
代码示例:取消任务
import java.util.concurrent.*;
public class CancelFutureExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 提交一个耗时任务
Future<Integer> future = executorService.submit(() -> {
Thread.sleep(5000); // 模拟耗时任务
return 123;
});
// 1 秒后取消任务
Thread.sleep(1000);
boolean cancelled = future.cancel(true); // 尝试中断任务
System.out.println("Task cancelled: " + cancelled);
executorService.shutdown();
}
}
在这个例子中:
- 提交一个需要 5 秒钟的任务。
- 等待 1 秒钟后取消任务。
cancel(true)
尝试中断正在运行的任务。
Future
与 Callable
类结合使用
Callable
接口与 Runnable
相似,都是可以在新线程中执行的任务,但 Callable
允许任务返回结果,并且可以抛出异常。ExecutorService.submit()
方法返回一个 Future
对象,Future
对象可用于获取 Callable
任务的结果。
代码示例:使用 Callable
和 Future
获取任务结果
import java.util.concurrent.*;
public class CallableFutureExample {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 使用 Callable 创建任务
Callable<Integer> task = () -> {
Thread.sleep(2000); // 模拟耗时任务
return 42;
};
// 提交任务并返回 Future 对象
Future<Integer> future = executorService.submit(task);
// 获取任务结果
Integer result = future.get(); // 阻塞直到任务完成
System.out.println("Task result: " + result); // 输出 42
executorService.shutdown();
}
}
在这个例子中:
- 使用
Callable
创建任务,任务执行完成后返回一个整数结果。 - 使用
Future.get()
获取结果。
总结
Future
类是 Java 并发编程中非常重要的接口,用于表示异步计算的结果。Future
提供了多种方法来操作异步任务,如获取结果 (get()
)、设置超时 (get(long, TimeUnit)
)、取消任务 (cancel()
)、检查任务状态 (isDone()
和isCancelled()
)。Future
常与ExecutorService
一起使用,通过submit()
方法提交任务,返回Future
对象以获取任务结果。Future
可以与Callable
结合使用,支持任务返回结果并抛出异常。- 在实际应用中,
Future
可以用于处理任务的异步执行、管理任务状态、控制任务超时等操作,尤其适合并发编程和多线程任务管理。
通过这些代码示例,你可以更好地理解和运用 Java 的 Future
类来处理并发任务。
发表回复