Java中Callable和Future——简介
来源:互联网 发布:蚂蚁金服 基金知乎 编辑:程序博客网 时间:2024/06/14 06:59
一、Java线程实现基础
java中实现一个线程的方法是继承(extends)Thread
类或者实现(implements)Runnable
接口(我个人认为通过线程池启线程也算是)。
继承Thread
类:
class A extends Thread{ @Override public void run() { //TODO } }
实现Runnable
接口:
class B implements Runnable{ @Override public void run() { //TODO } }
抑或分别使用匿名内部类,如下:
new Thread(){ public void run() { //TODO 操作 };}.start();
new Thread( new Runnable() { @Override public void run() { //TODO 操作 } }).start();
其实Thread
类自身就实现了Runnable
接口:
public class Thread implements Runnable{}
二、Callable和Runnable
Callable
和Runnable
接口申明定义分别如下:
/** * A task that returns a result and may throw an exception. * Implementors define a single method with no arguments called * {@code call}. * * <p>The {@code Callable} interface is similar to {@link * java.lang.Runnable}, in that both are designed for classes whose * instances are potentially executed by another thread. A * {@code Runnable}, however, does not return a result and cannot * throw a checked exception. * * <p>The {@link Executors} class contains utility methods to * convert from other common forms to {@code Callable} classes. * */@FunctionalInterfacepublic interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception;}
public interface Runnable { public abstract void run();}
它们都只有一个方法。相对而言,我们对Runnable
接口还是比较熟悉。如Callable
接口注释所说,我们知道Callable
和Runnable
类似,都是为其实例可能由另一个线程执行而设计。但是Callable
接口是泛型形式,call()
方法,有返回值且可抛出异常,即可返回线程执行结果。
三、Future和FutureTask
3.1、Future介绍:
Future
可以对具体的Callable
任务进行相关操作:取消/中断当前任务、查询任务是否完成、获取任务结果。其中get()方法会阻塞,直到任务完成返回结果,下一篇介绍其实现原理。Future声明如下(详细请见JDK文档):
public interface Future<V> {//泛型接口 /** * 取消/中断当前任务 */ boolean cancel(boolean mayInterruptIfRunning); /** *是否已取消/中断当前任务 */ boolean isCancelled(); /** * 查询任务是否完成 */ boolean isDone(); /** * 获取任务结果(会阻塞) */ V get() throws InterruptedException, ExecutionException; /** * 获取任务结果(会阻塞) */ V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
在Future
接口说明处已给出了伪代码来说明如何使用:
interface ArchiveSearcher { String search(String target); }class App { ExecutorService executor = ... ArchiveSearcher searcher = ... void showSearch(final String target) throws InterruptedException { Future<String> future = executor.submit(new Callable<String>() { public String call() { return searcher.search(target);// 异步线程处理搜索 }}); displayOtherThings(); // 在异步搜索的同时,在当前线程中,我们同时干别的事情,爽哉 try { displayText(future.get()); // 通过Future获取异步任务结果 } catch (ExecutionException ex) { cleanup(); return; } } }}
3.2、FutureTask介绍:
在Future
接口说明处同时也提到其具体实现类FutureTask
。先看一下如下类图:
可见FutureTask
则是一个RunnableFuture
,而RunnableFuture
则既继承了Runnbale
又继承了Futrue
:
public interface RunnableFuture<V> extends Runnable, Future<V> { void run(); }
public class FutureTask<V> implements RunnableFuture<V>{}
另,查看源码发现其构造函数依赖注入Runnbale
或Callable
,且Runnable
会被Executors.callable()转换为Callable
类型,即FutureTask
最终都是执行Callable
类型式任务:
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable}/**当不需要返回值时,result可以传null*/ public FutureTask(Runnable runnable, V result) { this.callable = Executors.callable(runnable, result);//被Executors.callable()转换为`Callable` this.state = NEW; // ensure visibility of callable}
Executors.callable()相关代码如下:
public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, 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()函数获取得到执行结果),上述Future
示例伪代码部分可以改造如下:
FutureTask<String> future = new FutureTask<String>(new Callable<String>() { public String call() { return searcher.search(target); }}); executor.execute(future);
或
FutureTask<String> future = new FutureTask<String>(new Callable<String>() { public String call() { return searcher.search(target); }}); new Thread(future).start();//没使用线程池,只是示意可以这么用
- Java中Callable和Future——简介
- Java中Callable和Future——引子
- Java并发——Callable和Future
- Callable和Future简介
- java callable和Future
- java.util.concurrent包(4)——Callable和Future
- java多线程总结笔记3——Callable和Future
- Java多线程——Callable、Future和FutureTask
- Java多线程(二)——Callable、Future和FutureTask
- JAVA并发编程(八)——Callable和Future
- JAVA多线程—Callable和Future的使用介绍
- Java多线程——Callable与Future
- Java—Callable,Future的使用
- Java线程:Callable和Future
- 【Java线程】Callable和Future
- Java线程:Callable和Future
- Java中的Callable和Future
- java多线程Callable和Future
- (安卓)Annotation(注解)实例
- 关于定时执行程序的一些想法
- 汉诺塔模板
- HQL初步了解占位符
- 链队列的基本操作(C++)
- Java中Callable和Future——简介
- SQL Server 2008 设置区分大小写
- spring boot静态资源文件的访问以及自定义
- Pycharm中使用Anaconda
- ZooKeeper-3.4.6集群安装配置
- OpenAirInterface运行OAI eNB和OAI UE without S1 接口
- opencv3学习之Point类
- HTML转PDF的问题
- MySQL 5.7.19安装目录下创建my.ini文件