源码|newTaskFor()和适配器模式

作者: 猴子007 | 来源:发表于2017-12-07 14:03 被阅读0次

AbstractExecutorService提供了一个创建任务的工厂方法——newTaskFor()。工厂方法大家很熟悉了,但newTaskFor()中用到的适配器模式却少有人提到。

JDK版本:oracle java 1.8.0_102

高能预警!这篇,又!短!又!没!用!

newTaskFor()和工厂方法模式

在AbstractExecutorService中,可以提交三种形式的task:

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task, result);
    execute(ftask);
    return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<T> ftask = newTaskFor(task);
    execute(ftask);
    return ftask;
}

三种形式类似,主要区别在于工厂方法AbstractExecutorService#newTaskFor():

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable);
}

直接调用了FutureTask的有参构造函数。

FutureTask实现了RunnableFuture接口:

public class FutureTask<V> implements RunnableFuture<V> 

该接口继承了Runnable、Future接口,并只有一个run方法。看下FutureTask的构造方法:

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
}

8行是一个适配器模式:

this.callable = Executors.callable(runnable, result);

通过静态工厂方法兼适配器Executors.callable()将Runnbale实例和result适配为Callable实例。

callable()和适配器模式

public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

RunnableAdapter完成实际的适配工作:

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;
    }
}

通过RunnableAdapter实例调用Callable#call()方法时,RunnableAdapter仅仅先调用Runnable#run(),再返回result。框架并没有什么地方会操作result——换句话说,这个适配器仅仅是让Runable实例能够被提交到ExecutorService中,与返回值并没有半分钱的关系

对,就是这么没用,但是用来讲适配器还是阔以的。

总结

通过AbstractExecutorService#newTaskFor()学习工厂方法模式,通过Executors.callable()学习适配器模式——嗯,,,虽然这个适配器没什么用。

另外,注意到AbstractExecutorService#newTaskFor()的访问权限为protected,我们可以在扩展类中覆写或直接使用该方法。如ForkJoinPool:

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
   return new ForkJoinTask.AdaptedRunnable<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
   return new ForkJoinTask.AdaptedCallable<T>(callable);
}

适配器走起。


本文链接:源码|newTaskFor()和适配器模式
作者:猴子007
出处:https://monkeysayhi.github.io
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名及链接。

相关文章

  • 源码|newTaskFor()和适配器模式

    AbstractExecutorService提供了一个创建任务的工厂方法——newTaskFor()。工厂方法大...

  • ListView详解--绘图、优化、适配器、观察者

    Android源码之ListView的适配器模式 Adapter Pattern适配器模式分为两种,即类适配器,对...

  • Android adapter ListView

    一、适配器模式 参考Android中Adapter的学习与思考Android源码之ListView的适配器模式 我...

  • java容器

    一、概览CollectionMap 二、容器中的设计模式迭代器模式适配器模式 三、源码分析ArrayListVec...

  • 【直通BAT】java容器考点总结和源码剖析

    一、概览 Collection Map 二、容器中的设计模式 迭代器模式 适配器模式 三、源码分析 ArrayLi...

  • 设计模式之适配器模式

    适配器模式: 类适配器模式、对象适配器模式、接口适配器模式 1.类适配器模式:新的接口出现了,但是和老的接口不兼容...

  • 设计模式:结构型

    享元模式 (Pools,Message) 代理模式 适配器模式 :类适配器和对象适配器 装饰者模式 外观模式 桥接...

  • 适配器模式

    先直观感受下什么叫适配器 适配器模式有类的适配器模式和对象的适配器模式两种不同的形式。 类适配器模式 对象适配器模...

  • Retrofit源码设计模式解析(下)

    本文将接着《Retrofit源码设计模式解析(上)》,继续分享以下设计模式在Retrofit中的应用: 适配器模式...

  • 设计模式详解——适配器模式

    本篇文章介绍一种设计模式——命令模式。本篇文章内容参考《JAVA与模式》之适配器模式,Android设计模式源码解...

网友评论

    本文标题:源码|newTaskFor()和适配器模式

    本文链接:https://www.haomeiwen.com/subject/prtmvxtx.html