Java ~ Executor【总结】

前言


 文章

  • 相关系列:《Java ~ Executor【目录】》(持续更新)
  • 相关系列:《Java ~ Executor【源码】》(学习过程/多有漏误/仅作参考/不再更新)
  • 相关系列:《Java ~ Executor【总结】》(学习总结/最新最准/持续更新)
  • 相关系列:《Java ~ Executor【问题】》(学习解答/持续更新)
  • 涉及内容:《Java ~ Executor ~ ExecutorService【总结】》
  • 涉及内容:《Java ~ Executor ~ ThreadPoolExecutor【总结】》

一 概述


 简介

    Executor(执行器)接口是执行器框架的最顶级接口,定义了执行器的概念,并明确了该框架的核心目标:将任务的递交与执行分离(并负责执行)。执行器接口的结构非常简单,只有一个execute(Runnable command)方法用于递交任务。正是因为该方法的存在,开发者无需再自我实现繁复的执行流程,而只需将任务创建并递交即可。任务的执行并不似想象中简单,它需要在性能和资源之间相互权衡,并要兼容实际场景的各项制约,还要满足预期设想的卓越效果,因此是一件费心费力的事情,特别是如果这件事情还要做很多次的话…任务的后续执行将彻底交由执行器负责,对开发者而言完全屏蔽,从而达到了“将任务的递交与执行分离(并负责执行)”的目的。因此可以说正是由于execute()方法的存在,执行器框架的作用才得以实现。

    在实际开发中,我们推荐使用执行器代替显式创建线程的方式来执行任务(这是最常见的任务执行方式,一般是为了获得更高的性能),以获取更好的执行效果,案例如下:

Executor executor = new Executor() {...}};
executor.execute(new RunnableTask());
executor.execute(new RunnableTask());

 同步/异步

    执行器接口并不严格(推荐但不强制)要求任务的执行是异步的。很多资料在讲述执行器框架时,都会直接将之称呼为“线程池”来阐述/强调其多线程及异步的特性,但这是完全错误的。之所以会有很多人将两者画上等号是因为在执行器接口的所有实现中ThreadPoolExecutor(线程池执行器)类是最贴合实际开发场景且往往是能最快最好获得收益的存在,使得众多开发者忽视(甚至是不知道)了其它实现而独尊“线程池”(网上随便找篇文章基本都是讲线程池的,其它的绝口不言)。但上文已经提及过,执行器框架的核心目标是“将任务的递交与执行分离(并负责执行)”,而对于任务的执行方式,则由各项子类自行实现,所谓的异步也只是众多执行方式的其中之一罢了。作为执行器框架的最顶级,执行器接口没有在任何方面强制在其子类在实现中只能使用异步的方式。因此请注意不要把执行器框架与异步强绑定,两者之间不存在必然关系。但话虽如此,采用异步却依旧最推荐的实现方案,因为这样往往能获得最高的效益。

    执行器接口的同步实现方式案例如下:

public class DirectExecutor implements Executor {
    
    public void execute(Runnable r) {
        // 直接使用调用线程对任务进行处理。
        r.run();
    }
  
}

 广泛实现

    执行器接口虽然在执行器框架中的拥有最高的地位,但由于其功能过于单一,因此在实际开发中往往会使用其子接口ExecutorService(执行器服务)代替。执行器服务接口是一个功能更加广泛的接口,在执行器接口的基础上引入了关闭、终止及结果等概念,更加贴合实际的使用需求,关于该接口的具体内容会在其专项文章中阐述,此处不再提及。

二 方法


    执行器接口只定义了一个execute(Runnable command)方法,用于执行向执行器递交的任务,是执行器框架一切的开始。

  • void execute(Runnable command) —— 执行 —— 执行指定任务。
    /**
     * Executes the given command at some time in the future.  The command may execute in a new thread, in a pooled thread, or in the
     * calling thread, at the discretion of the {@code Executor} implementation.
     * 在未来的某个时间执行指定的命令。这个命令可能在一个新线程、一个池线程或者在调用线程中执行,这取决于执行器的实现。
     *
     * @param command the runnable task 可执行任务
     * @throws RejectedExecutionException if this task cannot be accepted for execution
     *                                    拒绝执行异常:如果这个任务无法被接受执行
     * @throws NullPointerException       if command is null
     *                                    空指针异常:如果命令为null
     * @Description: 名称:执行
     * @Description: 作用:执行指定任务。
     * @Description: 逻辑:~
     */
    void execute(Runnable command);

你可能感兴趣的:(Java,#,Executor,java,Executor,Java)