Java多线程:Runnable、Callable、Future和FutureTask的关系与用法

0 下载量 41 浏览量 更新于2024-08-03 收藏 121KB DOCX 举报
"这篇文档探讨了Java多线程中Runnable、Callable、Future和FutureTask之间的关系,以及它们在异步任务处理中的应用。" 在Java多线程编程中,Runnable和Callable是两种常见的任务接口,它们都用于表示可执行的任务,但各有不同的特点。 1. Runnable接口是最基础的多线程任务接口,它的`run()`方法没有返回值,主要用于执行无返回结果的任务。在Java线程模型中,可以直接将Runnable对象传递给Thread的构造函数,创建并启动新线程。然而,由于`run()`方法不支持返回值,因此对于那些需要获取任务执行结果的场景,Runnable就显得力不从心。 2. Callable接口弥补了Runnable的不足,它的`call()`方法可以返回一个泛型结果,使得我们可以从异步任务中获取到计算的结果。Callable对象不能直接与Thread配合使用,而是常常与线程池(如ThreadPoolExecutor)结合,通过`submit()`方法提交任务。提交后,线程池会返回一个实现了Future接口的对象,该对象代表了异步执行的任务。 3. Future接口是Java并发包中一个非常重要的接口,它提供了对异步任务状态的查询和控制功能。Future对象提供了5个方法,包括: - `get()`: 获取任务的执行结果,如果任务尚未完成,会阻塞直到任务完成。 - `isDone()`: 检查任务是否已经完成。 - `isCancelled()`: 检查任务是否已被取消。 - `cancel(boolean mayInterruptIfRunning)`: 尝试取消正在执行的任务,mayInterruptIfRunning参数决定是否中断正在执行的任务。 - `get(long timeout, TimeUnit unit)`: 在指定等待时间后,获取任务结果,超时后抛出TimeoutException。 4. FutureTask是Future接口的一个实现,同时它也是Runnable接口的实现,这意味着它可以被直接提交给Thread执行。FutureTask内部封装了一个Callable任务,提供了完整的生命周期管理,包括任务的执行、结果的获取和取消等操作。在使用线程池时,如果不直接使用Callable,而是先将其包装成FutureTask,再提交给线程池,也可以方便地利用Future接口的方法来管理任务。 总结来说,Runnable和Callable分别对应无返回值和有返回值的线程任务,而Future和FutureTask则是用于管理和控制这些任务的工具。在实际开发中,尤其是涉及到异步计算和结果获取时,Callable和Future接口的组合使用可以提供更强大的功能。线程池通过submit()方法的调用,使得我们能够灵活地管理和控制异步任务,提高了代码的可读性和可维护性。

package step2; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; // ---------------------Begin------------------------ //tips: 输出语句为:Thread.currentThread().getName()+"的call()方法在运行" //定义一个实现Callable接口的实现类,类名必须命名为MyThread_callable class MyThread_callable<T> implements Callable<T> { public T call() throws Exception { return (T) (Thread.currentThread().getName() + "的call()方法在运行"); }} // ---------------------End------------------------ public class CallableExample { public static void main(String[] args) throws InterruptedException, ExecutionException { // 创建Callable接口的实现类对象 MyThread_callable myThread3 = new MyThread_callable(); // 使用FutureTask封装Callable接口 FutureTask<Object> ft1 = new FutureTask<>(myThread3); // 使用Thread(Runnable target ,String name)构造方法创建线程对象 Thread thread1 = new Thread(ft1, "thread1"); // 创建并启动另一个线程thread2 FutureTask<Object> ft2 = new FutureTask<>(myThread3); Thread thread2 = new Thread(ft2, "thread2"); // ---------------------Begin------------------------ // 调用线程对象的start()方法启动线程 System.out.println(thread1.start()) ; System.out.println(thread2.start()) ; // 可以通过FutureTask对象的方法管理返回值 Object result1 = ft1.get(); Object result2 = ft2.get(); System.out.println(result1); System.out.println(result2); // ---------------------End------------------------ } }

2023-06-11 上传