`
men4661273
  • 浏览: 278215 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java的Thread,Runnable、Callable、Future、FutureTask、Executors,ExecutorService

阅读更多

定义解释 

 

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中的Runnable、Callable、Future和FutureTask是Java多线程编程中的核心概念,它们各自扮演着不同的角色,共同协作以实现并发任务的管理和执行。 1. **Runnable**: Runnable是最基本的多线程接口,它只有一个`...

    Java中Future、FutureTask原理以及与线程池的搭配使用

    Java中的`Future`和`FutureTask`是并发编程中重要的工具,它们允许程序异步执行任务并获取结果。`Future`接口提供了对异步计算结果的访问和控制,而`FutureTask`是`Future`的一个具体实现,它还同时实现了`Runnable`...

    Android(Java)之多线程结果返回——Future 、FutureTask、Callable、Runnable

    `Future`、`FutureTask`、`Callable`和`Runnable`是Java并发编程中的核心接口和类,它们在Android开发中同样有着广泛的应用。下面将详细介绍这些概念以及它们如何协同工作。 1. `Runnable`: 这是Java中最基础的多...

    JAVA中Callable的使用

    `FutureTask`是`Future`的一个具体实现,它同时也是一个`Runnable`,可以直接提交给ExecutorService。`FutureTask`的构造函数接受一个Callable对象,当任务执行完成后,可以通过`FutureTask`的`get()`方法获取结果。...

    浅谈在Java中使用Callable、Future进行并行编程

    FutureTask是Future接口的一个具体实现,它同时实现了Runnable接口,因此可以提交给ExecutorService执行。FutureTask有两个构造函数,分别接受Callable和Runnable对象,以及一个可选的结果值。 下面是一个使用...

    futuretask用法及使用场景介绍

    FutureTask的实现机制是通过传入Runnable或者Callable的任务给FutureTask,然后调用其run方法或通过线程池执行,最后可以在外部通过FutureTask的get方法异步获取执行结果。 FutureTask还可以确保即使调用了多次run...

    java多线程返回值使用示例(callable与futuretask)

    为了解决这个问题,Java提供了`Callable`接口和`FutureTask`类,它们是实现多线程返回值的关键工具。 `Callable`接口类似于`Runnable`,但比它功能更强大。`Callable`接口中的`call()`方法可以返回一个结果,并且...

    Java多线程实现的四种方式

    在Java中,实现多线程有四种主要方法:继承Thread类、实现Runnable接口、使用ExecutorService和使用Callable与Future。下面将详细探讨这四种方式。 1. 继承Thread类 在Java中,我们可以直接继承Thread类并重写其run...

    java实现线程的异步

    FutureTask 是一个实现了 Runnable 和 Future 的类,可以将 Callable 包装成 Runnable,并返回计算结果: ```java Callable&lt;Integer&gt; callable = () -&gt; { // 执行计算任务,返回结果 return 42; }; FutureTask...

    Java concurrency线程池之Callable和Future_动力节点Java学院整理

    Java concurrency线程池之Callable和Future Java concurrency是一个重要的概念,在Java编程中,线程池是一个关键组件。今天,我们将详细介绍Java concurrency线程池之Callable和Future,这两个组件在Java并发编程中...

    Java FutureTask类使用案例解析

    Callable和Runnable的转换可以使用Executors提供的方法,将Runnable转换为Callable,例如: ```java public static &lt;T&gt; Callable&lt;T&gt; callable(Runnable task, T result) { if (task == null) throw new ...

    Callable接口源码阅读1

    例如,可以使用`Executors.callable(Runnable task, V result)`将一个Runnable转换为Callable,这样Runnable的任务就可以返回一个结果。 7. **应用场景** Callable常用于FutureTask或者ExecutorService中。...

    顶层接口Executors详解

    2. 然后可以把Runnable对象直接交给ExecutorService执行,或者把Runnable对象或Callable对象提交给ExecutorService执行。 3. 最后,主线程可以执行FutureTask.get()方法来等待任务执行完成。主线程也可以执行...

    FutureTask学习

    总之,`FutureTask`是Java并发编程中用于异步计算的一个强大工具,它结合了`Runnable`和`Callable`的优点,提供了任务执行状态的检查以及结果的获取。理解和熟练使用`FutureTask`对于编写高效并发程序至关重要。在...

    java多线程编程同步器Future和FutureTask解析及代码示例

    在Java并发编程中,通常我们会使用`ExecutorService`来提交任务,而`Future`和`FutureTask`就是与这些任务交互的关键。 首先,`Future`是一个接口,它提供了一种机制来检查异步计算是否完成,以及在计算完成后获取...

    java面试精华14

    本文将深入探讨如何利用Java提供的`Runnable`与`Callable`接口配合`Future`或`FutureTask`来实现这一功能。 #### 一、基础知识回顾 在开始之前,我们先简要回顾一下`Runnable`和`Callable`这两个接口的基本概念: ...

    java8源码-concurrency:java并发总结

    java8 源码 Java 并发多线程从简到全 参考: 目录: [TOC] 相关文档: kwseeker/netty Executors线程池.md 1 基本概念 1.1 CPU与线程的关系 1.2 线程与进程的区别和关系 1.3 吞吐量 1.4 线程安全 1.5 线程声明周期 ...

    Java多线程之Callable接口的实现

    FutureTask类同时实现了Future和Runnable接口,因此它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。例如: Callable&lt;Integer&gt; mycallabletask = new MyCallableTask(); FutureTask...

    四种方式实现线程

    本文将深入探讨四种实现线程的方法:Thread类、Runnable接口、Callable接口以及ExecutorService。每种方法都有其特定的应用场景和优势,下面我们将逐一详细讲解。 1. **Thread类** 当直接继承`java.lang.Thread`类...

    31 凭票取餐—Future模式详解.pdf

    然后,将Callable对象包装成一个FutureTask,FutureTask同时实现了Runnable接口,因此可以被线程执行。 2. Future的使用 示例代码中,创建了一个`FutureTask&lt;String&gt; cookTask`,它的构造函数接收一个Callable对象...

Global site tag (gtag.js) - Google Analytics