Java中的Runnable、Callable、Future、FutureTask的区别
本文转载自:http://blog.csdn.net/bboyfeiyu/article/details/24851847
Runnable
其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 :
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
Callable
Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :
可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。
Future
Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行
取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下 :
/**
* @see FutureTask
* @see Executor
* @since 1.5
* @author Doug Lea
* @param <V> The result type returned by this Future's <tt>get</tt> method
*/
public interface Future<V> { /**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task. *
*/
boolean cancel(boolean mayInterruptIfRunning); /**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally.
*/
boolean isCancelled(); /**
* Returns <tt>true</tt> if this task completed.
*
*/
boolean isDone(); /**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
*/
V get() throws InterruptedException, ExecutionException; /**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
FutureTask
FutureTask则是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口,
另外它还可以包装Runnable和Callable<V>, 由构造函数注入依赖。
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
} public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
RunnableAdapter适配器
/**
* A callable that runs given task and returns given result
*/
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;
}
}
由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。
并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、
Runnable,又是包装了Callable(
如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。
简单示例
package com.effective.java.concurrent.task; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask; /**
*
* @author mrsimple
*
*/
public class RunnableFutureTask { /**
* ExecutorService
*/
static ExecutorService mExecutor = Executors.newSingleThreadExecutor(); /**
*
* @param args
*/
public static void main(String[] args) {
runnableDemo();
futureDemo();
} /**
* runnable, 无返回值
*/
static void runnableDemo() { new Thread(new Runnable() { @Override
public void run() {
System.out.println("runnable demo : " + fibc(20));
}
}).start();
} /**
* 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V
* call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
* ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
*/
static void futureDemo() {
try {
/**
* 提交runnable则没有返回值, future没有数据
*/
Future<?> result = mExecutor.submit(new Runnable() { @Override
public void run() {
fibc(20);
}
}); System.out.println("future result from runnable : " + result.get()); /**
* 提交Callable, 有返回值, future中能够获取返回值
*/
Future<Integer> result2 = mExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return fibc(20);
}
}); System.out
.println("future result from callable : " + result2.get()); /**
* FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
* 另外它还可以包装Runnable(实际上会转换为Callable)和Callable
* <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
* ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
*/
FutureTask<Integer> futureTask = new FutureTask<Integer>(
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return fibc(20);
}
});
// 提交futureTask
mExecutor.submit(futureTask) ;
System.out.println("future result from futureTask : "
+ futureTask.get()); } catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} /**
* 效率底下的斐波那契数列, 耗时的操作
*
* @param num
* @return
*/
static int fibc(int num) {
if (num == 0) {
return 0;
}
if (num == 1) {
return 1;
}
return fibc(num - 1) + fibc(num - 2);
} }
Java中的Runnable、Callable、Future、FutureTask的区别的更多相关文章
- Java中的Runnable、Callable、Future、FutureTask的区别与示例
Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. ...
- Java 并发编程——Callable+Future+FutureTask
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- Java线程池(Callable+Future模式)
转: Java线程池(Callable+Future模式) Java线程池(Callable+Future模式) Java通过Executors提供四种线程池 1)newCachedThreadPoo ...
- Java中public,private,protected,和默认的区别
Java中public,private,protected,和默认的区别 1.private修饰词,表示成员是私有的,只有自身可以访问: 2.protected,表示受保护权限,体现在继承,即子类可以 ...
- 【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别
Java中的"equals"和"=="的用法及区别 在初学Java时,可能会经常碰到下面的代码: String str1 = new String(" ...
- java中public与private还有protect的区别
java中public与private还有protect的区别 总是忘记.
- Java中的基本类型和引用类型变量的区别
Java中的基本类型和引用类型变量的区别 学了一年多,说实话你要我说这些东西我是真说不出来是啥意思 基本类型: 基本类型自然不用说了,它的值就是一个数字,一个字符或一个布尔值. 引用类型: ...
- JAVA中局部变量 和 成员变量有哪些区别
JAVA中局部变量 和 成员变量有哪些区别 1.定义的位置不一样<重点>***局部变量:在方法的内部成员变量:在方法的外部,直接写在类当中 2.作用范围不一样<重点>***局部 ...
- java 中,for、for-each、iterator 区别
java 中,for.for-each.iterator 区别: 无论是在数组中还是在集合中,for-Each加强型for循环都是它们各自的普通for循环的一种"简写方式",即两者 ...
- java中String new和直接赋值的区别
Java中String new和直接赋值的区别 对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才 ...
随机推荐
- Hibernate5笔记7--Hibernate缓存机制
Hibernate缓存机制: 缓存范围: 应用程序中根据缓存的范围,可以将缓存分为三类: (1)事务范围缓存(单Session,即一级缓存) 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓 ...
- MySQL主从复制-指定数据库复制
在/etc/my.cnf添加需要进行同步的数据库信息 #需要进行同步的数据库 #replicate-do-db=custmgr #replicate-do-db=sdata #replicate-ig ...
- Github授权新的设备ssh接入
为Mac生成公钥 步骤: 检查本机是否已有公钥 ls -la ~/.ssh 将原来的公钥删除 rm -rf ~/.ssh 生成新的公钥(填自己的邮箱),然后除了密码,一路默认 ssh-keygen - ...
- MySQL通过rpm安装及其单机多实例部署
1. CentOS 下安装 MySQL Oracle 收购 MySQL 后,CentOS 为避免 MySQL 闭源的风险,改用 MySQL 的分支 MariaDB:MariaDB 完全兼容 MySQL ...
- jmock2.5 基本教程
目录 第0章 概述 第1章 jmock初体验 第2章 期望 第3章 返回值 第4章 参数匹配 第5章 指定方法调用次数 第6章 指定执行序列 第7章 状态机 第0章 概述 现在的dev不是仅仅要写co ...
- SSIS 学习之旅 FTP文件传输-FTP任务
这一章主要讲解一下FTP控件. 设计: 通过Demon库的Users表数据生成CSV文件. 生成后的CSV文件抛送到FTP指定目录下. 其他控件的使用这里就不做详细讲解了.大家如果有不懂得可以 ...
- 一步一步学习IdentityServer4 (6) Connect-OpenId Cookies SignIn SignOut 那些事
先来看下下面的配置: JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication( o ...
- 专业分析docker的分层存储技术
话不在多,指明要点! 联合挂载是用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统视图的途径, 是下层存储驱动(aufs.overlay等) 实现分层合并的方式. 所以严格来说,联合挂载 ...
- Factroy 简单工厂
意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类. Factory Method使一个类的实例化延迟到其子类. 动机 框架使用抽象类定义和维护对象之间的关系.这些对象的创建通常也由框架负责. ...
- Jquery~跨域异步上传文件
先说明白 这个跨域异步上传功能我们借助了Jquery.form插件,它在异步表单方面很有成效,而跨域我们会在HTTP响应头上添加access-control-allow-method,当然这个头标记只 ...