定义解释
Runnable:接口,线程任务的接口定义,一个run方法,无返回值,创建的线程无法获取返回值。
Callable<T>:接口,线程任务的接口定义,一个call方法,有返回值,返回值类型为指定的泛型。
Future<T>:接口,是Callable、Runnable(FutureTask可以将Runnable转换为Callable类型)的调度容器,它可以对执行的线程进行取消,查询是否完成,获取结果等操作,get方法获取结果会阻塞,直到任务返回结果。
FutureTask<T>:类,实现RunnableFuture接口的类,RunnableFuture继承了Runnable、Future<T>,所以相当于是实现类Runnable、Callable<T>接口的一个实现类,相当于具有Runnable和Future的功能。
Thread:类,实现Runnable接口的类,所以具有Runnable的特性,它的功能还有包装线程任务,作为异步任务的执行者,管理异步任务。
Executors:类,创建各种线程池,还有将Runnable转换为Callable的方法等。
ExecutorService:接口,各种类型线程池的接口定义。
所以创建线程有三种方式:
1、实现Runnable接口,交给Thread实例或者线程池去执行,无法获取任务执行结果。
2、Thread实现了Runnable接口,所以可以继承Thread类,直接执行或者交给线程池去执行,无法获取任务执行结果。
3、实现Callable<T>接口,并使用FutureTask<T>进行包装,交给Thread实例或者线程池去执行,可以获取到任务执行结果,但是使用get获取任务执行结果时会阻塞,直到任务返回结果。
FutureTask可以包装一个Runnable实例,实质上是将Runnable转换成了一个Callable,并赋予默认返回值。
//FutureTask的一个构造方法: public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
//Executors的callable方法,返回一个RunnableAdapter实例: public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); }
//RunnableAdapter是Executors的静态内部类,实现Callable接口 static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } }来看下线程的实现方法:
方法一(TaskA实现Runnable接口):
Thread thread = new Thread(new TaskA()); thread.start();
方法二(Task继承Thread类):
TaskB task = new TaskB(); task.start();方法三(实现Callable接口结合FutureTask):
TaskC task = new TaskC(); //带有返回值的线程 FutureTask<Integer> future = new FutureTask<Integer>(task); Thread thread = new Thread(future); thread.start(); System.out.println("获取Callable任务的返回值:" + future.get()); //FutureTask也可以运行Runnable任务,FutureTask会在构造方法里面将Runnable转换为Callable, 指定的返回值为 线程的返回值 FutureTask<Integer> future1 = new FutureTask<Integer>(new TaskA(), 2); thread = new Thread(future1); thread.start(); System.out.println("获取Runnable任务的返回值:" + future1.get());补充一个使用线程池调度的方式:
//创建一个同时只能执行一个任务的线程池 ExecutorService service = Executors.newSingleThreadExecutor(); TaskA taskA = new TaskA(); TaskB taskB = new TaskB(); //execute只能执行Runnable类型的任务,没有返回值 service.execute(taskA); service.execute(taskB); //submit执行Runnable类型的任务,返回值为null Future<?> future = service.submit(taskA); System.out.println("获取Runnable任务的返回值:" + future.get()); future = service.submit(taskA,2); System.out.println("获取Runnable任务的返回值:" + future.get()); TaskC taskCallable = new TaskC(); future = service.submit(taskCallable); System.out.println("获取Callable任务的返回值:" + future.get());
最后比较以下三种方式的特点:
1、Runnable方式:只提供任务实例, 需要依赖任务调度器执行,无返回值。
2、Thread方式:实现了Runnable接口,可以包装任务实例,并作为任务调度器直接执行,无返回值。也可以说Thread是间接地通过实现Runnable接口才具备了创建线程任务的功能,哈哈。但是由于Thread可以作为线程任务调度执行器,所以他具有线程管理的功能,比如join,interrupt等。
3、Callable方式:跟Runnable相似,但可以获取线程执行的返回值,但是获取返回值时会阻塞,直到线程任务返回。
所以只创建任务的话,一般用Runnable,多个线程之间进行通信交互时,用Thread,需要获取返回值时,用Callable。
以上为个人理解,如有不对请拍砖,谢谢~
相关推荐
Java中的Runnable、Callable、Future和FutureTask是Java多线程编程中的核心概念,它们各自扮演着不同的角色,共同协作以实现并发任务的管理和执行。 1. **Runnable**: Runnable是最基本的多线程接口,它只有一个`...
Java中的`Future`和`FutureTask`是并发编程中重要的工具,它们允许程序异步执行任务并获取结果。`Future`接口提供了对异步计算结果的访问和控制,而`FutureTask`是`Future`的一个具体实现,它还同时实现了`Runnable`...
`Future`、`FutureTask`、`Callable`和`Runnable`是Java并发编程中的核心接口和类,它们在Android开发中同样有着广泛的应用。下面将详细介绍这些概念以及它们如何协同工作。 1. `Runnable`: 这是Java中最基础的多...
`FutureTask`是`Future`的一个具体实现,它同时也是一个`Runnable`,可以直接提交给ExecutorService。`FutureTask`的构造函数接受一个Callable对象,当任务执行完成后,可以通过`FutureTask`的`get()`方法获取结果。...
FutureTask是Future接口的一个具体实现,它同时实现了Runnable接口,因此可以提交给ExecutorService执行。FutureTask有两个构造函数,分别接受Callable和Runnable对象,以及一个可选的结果值。 下面是一个使用...
FutureTask的实现机制是通过传入Runnable或者Callable的任务给FutureTask,然后调用其run方法或通过线程池执行,最后可以在外部通过FutureTask的get方法异步获取执行结果。 FutureTask还可以确保即使调用了多次run...
为了解决这个问题,Java提供了`Callable`接口和`FutureTask`类,它们是实现多线程返回值的关键工具。 `Callable`接口类似于`Runnable`,但比它功能更强大。`Callable`接口中的`call()`方法可以返回一个结果,并且...
在Java中,实现多线程有四种主要方法:继承Thread类、实现Runnable接口、使用ExecutorService和使用Callable与Future。下面将详细探讨这四种方式。 1. 继承Thread类 在Java中,我们可以直接继承Thread类并重写其run...
FutureTask 是一个实现了 Runnable 和 Future 的类,可以将 Callable 包装成 Runnable,并返回计算结果: ```java Callable<Integer> callable = () -> { // 执行计算任务,返回结果 return 42; }; FutureTask...
Java concurrency线程池之Callable和Future Java concurrency是一个重要的概念,在Java编程中,线程池是一个关键组件。今天,我们将详细介绍Java concurrency线程池之Callable和Future,这两个组件在Java并发编程中...
Callable和Runnable的转换可以使用Executors提供的方法,将Runnable转换为Callable,例如: ```java public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new ...
例如,可以使用`Executors.callable(Runnable task, V result)`将一个Runnable转换为Callable,这样Runnable的任务就可以返回一个结果。 7. **应用场景** Callable常用于FutureTask或者ExecutorService中。...
2. 然后可以把Runnable对象直接交给ExecutorService执行,或者把Runnable对象或Callable对象提交给ExecutorService执行。 3. 最后,主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程也可以执行...
总之,`FutureTask`是Java并发编程中用于异步计算的一个强大工具,它结合了`Runnable`和`Callable`的优点,提供了任务执行状态的检查以及结果的获取。理解和熟练使用`FutureTask`对于编写高效并发程序至关重要。在...
在Java并发编程中,通常我们会使用`ExecutorService`来提交任务,而`Future`和`FutureTask`就是与这些任务交互的关键。 首先,`Future`是一个接口,它提供了一种机制来检查异步计算是否完成,以及在计算完成后获取...
本文将深入探讨如何利用Java提供的`Runnable`与`Callable`接口配合`Future`或`FutureTask`来实现这一功能。 #### 一、基础知识回顾 在开始之前,我们先简要回顾一下`Runnable`和`Callable`这两个接口的基本概念: ...
java8 源码 Java 并发多线程从简到全 参考: 目录: [TOC] 相关文档: kwseeker/netty Executors线程池.md 1 基本概念 1.1 CPU与线程的关系 1.2 线程与进程的区别和关系 1.3 吞吐量 1.4 线程安全 1.5 线程声明周期 ...
FutureTask类同时实现了Future和Runnable接口,因此它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。例如: Callable<Integer> mycallabletask = new MyCallableTask(); FutureTask...
本文将深入探讨四种实现线程的方法:Thread类、Runnable接口、Callable接口以及ExecutorService。每种方法都有其特定的应用场景和优势,下面我们将逐一详细讲解。 1. **Thread类** 当直接继承`java.lang.Thread`类...
然后,将Callable对象包装成一个FutureTask,FutureTask同时实现了Runnable接口,因此可以被线程执行。 2. Future的使用 示例代码中,创建了一个`FutureTask<String> cookTask`,它的构造函数接收一个Callable对象...