定义解释
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的比较的相关资料,需要的朋友可以参考下
2 如何使用FutureTask 、Future、Callable、线程池实现线程2.1 FutureTask + Callable实现多线程2.2 线程池+Future+Callable 实现多线程3 Runnable、Callable、Future和FutureTask之间的关系3.1 整体关系介绍3.2 ...
主要介绍了Java 线程(Thread,Runnable,Callable)实例详解的相关资料,这里对java 线程的三种方法进行了对比,需要的朋友可以参考下
Executor: 一个接口,其定义了一个接收Runnable对象的方法...new Thread(new RunnableTask())).start(),但在Executor中,可以使用Executor而不用显示地创建线程:executor.execute(new RunnableTask()); // 异步执行
http://blog.csdn.net/yangzhaomuma/article/details/51722779
Java中Runnable和Thread的区别
在Java中创建线程有两种方法:使用Thread类和使用Runnable接口。在使用Runnable接口时需要建立一个Thread实例。因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例。
大家都知道Runnable和Callable接口都可以作为其他线程执行的任务,但是Runnable接口的run方法没有返回值,而Callable接口的call方法有返回值,那么Callable接口是如何做到的呢?在此我给出一个Demo,看看通过...
在Java SE5中引入的Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call()中返回的值,并且必须使用ExecutorService.submit()方法调用它。 import java.util.ArrayList; import java.util....
Java中Runnable和Thread的区别分析.rar
面向小白学习法——Thread和Runnable,扩展Callable! Thread和Runnable的区别 (Callable扩展) 线程 Thread Runnable 扩展——Callable 面向小白学习法——Thread和Runnable,扩展Callable! Thread和...
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用...Callable是需要使用java.util.concurrent.ExecutorService.submit(Callable)方
java8 源码 Java 并发多线程从简到全 参考: 目录: [TOC] 相关文档: kwseeker/netty Executors线程池.md 1 基本概念 1.1 CPU与线程的关系 1.2 线程与进程的区别和关系 1.3 吞吐量 1.4 线程安全 1.5 线程声明周期 ...
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。接下来通过本文给大家浅析Java中Runnable和Thread的区别,一起看看吧
主要介绍了Java向Runnable线程传递参数方法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
目录: 简介 Callable接口的基本用法 2.1 创建Callable任务 2.2 提交Callable任务 2.3 获取任务执行结果 ...Callable与Runnable的对比 Callable的异常处理 Callable的应用场景 最佳实践与注意事项
主要介绍了Java中继承thread类与实现Runnable接口的比较的相关资料,需要的朋友可以参考下
1. 在Java中负责实现线程功能的类是java.lang.Thread 类。 2. 可以通过创建 Thread的实例来创建新的线程。 3. 每个线程都是通过某个特定的Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。 4. ...
1、 Runnable接口与Thread类 1 2、 两个创建线程方法的比较 3 3、 几个常用的改变线程状态的方法 3 4、 线程的同步机制 8 5、 死锁 11 6、 线程间通信,也叫生产者与消费者问题 15 7、 浅析 Java Thread.join() : ...