Future模式是多线程开发中常用常见的一种设计模式,它的核心思想是异步调用。在调用一个函数方法时候,如果函数执行很慢,我们就要进行等待,但这时我们可能不着急要结果,因此我们可以让被调者立即返回,让它在后台慢慢处理这个请求,对于调用者来说可以先处理一些其他事物,在真正需要数据的场合再去尝试获得需要的数据。对于Future模式来说,虽然它无法立即给出你需要的数据,但是它们返回一个契约给你,将来你可以凭借这个契约去重新获取你需要的信息。
Java中的Future对象主要用于异步编程,允许程序在等待某个操作完成时继续执行其他任务。
-
Future的基本概念:Future对象代表了一个异步计算的结果。当这个计算完成时,结果会被保存在Future对象中。通过Future,我们可以暂时处理其他任务,而无需一直等待结果,等异步任务执行完毕再返回其结果1。
-
Future的使用场景:
- 当执行一个长时间运行的任务时,使用Future可以让我们暂时去处理其他的任务,等长任务执行完毕再返回其结果。这适用于计算密集场景、处理大数据量、远程方法调用等场景2。
- Future模式可以让程序更加灵活和高效,优化程序的性能,提高用户体验,因为用户不需要等待一个操作完成才能进行下一个操作3。
-
Future的主要方法:
get()方法用于获取异步任务的结果。如果任务还没有结束,get()方法会阻塞线程直到任务完成。此外,还有一个带超时的get(long timeout, TimeUnit unit)方法,允许在等待一定时间后如果任务仍未完成则抛出TimeoutException1。isDone()方法用于检查异步任务是否已经完成3。
-
Future的实现:
- 通过
ExecutorService的submit()方法提交一个Callable任务来获取一个Future对象。Callable接口类似于Runnable,但它允许返回一个结果12。 - 使用
Future时,可以通过实现Callable接口并重写call()方法来定义异步任务。call()方法可以抛出异常并返回结果12。
- 通过
-
使用Future的注意事项:
- 当使用
get()方法获取结果时,如果任务未完成,调用线程会被阻塞。因此,需要谨慎处理这种情况,避免死锁或资源浪费1。 - 在多线程环境中使用
Future时,应注意线程安全和资源管理,确保在任务完成后正确关闭资源3。
- 当使用
通过上述介绍,我们可以看到Java中的Future机制为并发编程提供了灵活的解决方案,使得程序能够在等待异步任务完成的同时继续执行其他任务,提高了程序的效率和响应性。
关键点
- Future用于表示异步执行的结果,能够对Runnable和Callable任务的执行结果进行管理。
- 通过Future对象的get()方法可以获取异步执行的结果,该方法会阻塞直到任务完成。
- Future提供了cancel方法用于取消尚未执行或正在执行的任务。
- isDone方法可以用来检查任务是否已经完成。
- CompletableFuture是对Future模式的增强版本,提供了回调机制以优化异步执行。
- CompletableFuture支持两个接口,分别是Future和CompletionStage,增强了异步编程的灵活性。
- Runnable和Callable分别用于没有返回结果和有返回结果的任务,使得Future能够更加有效地管理不同类型的任务。
代码示例
public class FutureTest {
public static void main(String[] args) throws Exception {
ExecutorService es = Executors.newFixedThreadPool(4);
Future<BigDecimal> future = es.submit(new Task("601857"));
System.out.println(future.get());
es.shutdown();
}
}
class Task implements Callable<BigDecimal> {
public Task(String code) {
}
@Override
public BigDecimal call() throws Exception {
Thread.sleep(1000);
double d = 5 + Math.random() * 20;
return new BigDecimal(d).setScale(2, RoundingMode.DOWN);
}
}