多线程 - Callable、Future 和 FutureTask 简单应用(一)

简介: 多线程 - Callable、Future 和 FutureTask 简单应用(一)

我们知道创建线程的方式有两种,一种是实现Runnable接口,另一种是继承Thread,但是这两种方式都有个缺点,那就是在任务执行完成之后无法获取返回结果,那如果我们想要获取返回结果该如何实现呢?java 为我们提供了 Callable 接口和 Future ,从JAVA SE 5.0开始引入了Callable和Future,通过它们构建的线程,在任务执行完成后就可以获取执行结果,这就是线程的第三种方式,那就是实现Callable接口。

Callable


@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

该接口声明了一个名称为 call() 的方法,同时这个方法可以有返回值 V,也可以抛出异常。无论是 Runnable 接口的实现类还是 Callable 接口的实现类,都可以被 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor 执行,ThreadPoolExecutor或ScheduledThreadPoolExecutor都实现了ExcutorService 接口,而因此 Callable 需要和Executor 框架中的 ExcutorService 结合使用,我们先看看 ExecutorService 提供的方法


public Future<?> submit(Runnable task) {
    return schedule(task, 0, NANOSECONDS);
}
public <T> Future<T> submit(Runnable task, T result) {
    return schedule(Executors.callable(task, result), 0, NANOSECONDS);
}
public <T> Future<T> submit(Callable<T> task) {
    return schedule(task, 0, NANOSECONDS);
}
  • 第一个方法:submit提交一个实现Runnable接口的任务,并且返回封装了异步计算结果的Future。
  • 第二个方法:submit提交一个实现Runnable接口的任务,并且指定了在调用Future的get方法时返回的result对象。
  • 第三个方法:submit提交一个实现Callable接口的任务,并且返回封装了异步计算结果的Future。

因此我们只要创建好我们的线程对象(实现Callable接口或者Runnable接口),然后通过上面3个方法提交给线程池去执行即可。还有点要注意的是,除了我们自己实现Callable对象外,我们还可以使用工厂类Executors来把一个Runnable对象包装成Callable对象。Executors工厂类提供的方法如下


public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}
public static Callable<Object> callable(Runnable task) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<Object>(task, null);
}

Future

Future接口是用来获取异步计算结果的,说白了就是对具体的Runnable或者Callable对象任务执行的结果进行获取(get()),取消(cancel()),判断是否完成等操作。Future接口的源码:


public interface Future<V> {
    // 如果任务还没有开始,执行 cancel() 方法将返回false,如果任务已经启动,执行 cancel(true) 方法将
    // 已中断执行此任务线程的方式来试图停止任务,如果停止成功,返回 true,当任务已经启动,执行
    // cancel(false) 方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回 false
    // 当任务已经完成,执行 cancel() 方法将返回 false ,mayInterruptlfRunning 参数表示是否中断执行中的
    // 线程,通过方法分析我们也知道实际上 Future 提供了 3 中可能:1.能够中断执行中的任务,2.判断
    // 任务是否执行完成,3.获取任务执行完成后的结果,但是 Future 是一个接口,我们无法直接创建对象
    // 因此就需要其实现类 FutureTask
    boolean cancel(boolean mayInterruptIfRunning);
    // 如果任务完成前被取消,则返回 true
    boolean isCancelled();
    // 如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回 true
    boolean isDone();
    // 该方法用于获取异步执行的结果,如果没有结果返回,该方法会一直阻塞直到任务执行完成
    V get() throws InterruptedException, ExecutionException;
    // 获取异步执行结果,如果没有结果返回,此方法会一直阻塞,但是会有时间的限制
    // 如果阻塞时间超过设定的 timeout 时间,该方法会抛出异常
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
目录
相关文章
|
1月前
|
Java 程序员
Java社招面试中的高频考点:Callable、Future与FutureTask详解
大家好,我是小米。本文主要讲解Java多线程编程中的三个重要概念:Callable、Future和FutureTask。它们在实际开发中帮助我们更灵活、高效地处理多线程任务,尤其适合社招面试场景。通过 Callable 可以定义有返回值且可能抛出异常的任务;Future 用于获取任务结果并提供取消和检查状态的功能;FutureTask 则结合了两者的优势,既可执行任务又可获取结果。掌握这些知识不仅能提升你的编程能力,还能让你在面试中脱颖而出。文中结合实例详细介绍了这三个概念的使用方法及其区别与联系。希望对大家有所帮助!
175 60
|
6月前
|
并行计算 Java 大数据
Callable和Future
Callable和Future
|
7月前
|
缓存 Java 调度
Java并发编程:深入解析线程池与Future任务
【7月更文挑战第9天】线程池和Future任务是Java并发编程中非常重要的概念。线程池通过重用线程减少了线程创建和销毁的开销,提高了资源利用率。而Future接口则提供了检查异步任务状态和获取任务结果的能力,使得异步编程更加灵活和强大。掌握这些概念,将有助于我们编写出更高效、更可靠的并发程序。
|
6月前
|
Java API 调度
JUC线程池: FutureTask详解
总而言之,FutureTask是Java并发编程中一个非常实用的类,它在异步任务执行及结果处理方面提供了优雅的解决方案。在实现细节方面可以搭配线程池的使用,以及与Callable接口的配合使用,来完成高效的并发任务执行和结果处理。
65 0
|
7月前
|
监控 Java 开发者
Java面试题:解释Java内存模型中的内存顺序规则,Java中的线程组(ThreadGroup)的工作原理,Java中的FutureTask的工作原理
Java面试题:解释Java内存模型中的内存顺序规则,Java中的线程组(ThreadGroup)的工作原理,Java中的FutureTask的工作原理
37 0
|
7月前
|
存储 算法 Java
Java面试题:详细描述Java堆内存的垃圾回收过程,解释Java中的线程池(ThreadPool)的工作原理,解释Java中的FutureTask的工作原理
Java面试题:详细描述Java堆内存的垃圾回收过程,解释Java中的线程池(ThreadPool)的工作原理,解释Java中的FutureTask的工作原理
47 0
|
9月前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
181 5
|
9月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
111 1
|
9月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。
|
Java
ExecutorService、Callable、Future实现有返回结果的多线程原理解析
ExecutorService、Callable、Future实现有返回结果的多线程原理解析
96 0