zoukankan      html  css  js  c++  java
  • JUC中Executor基本知识

    Future And Callable

    引用
    http://www.cnblogs.com/dolphin0520/p/3949310.html
    http://www.iocoder.cn/JUC/
    Future用于返回任务,带有返回值

    Future

    Callable和Runnable 的区别

    Runnable是在JDK1.0版本引入的,唯一的一个方法是void run()。多插入一句,JDK设计者设计的类是真的强从1.0用到现在还在用

    Callable是在JDK1.5版本引入的,唯一的一个方法是void call()和Runnable中的void run()对应,Callable是做为Executor实际调用的对象,尽管会经过复杂的封装,比如FutureTask继承于RunnabFuture,而RunnaFuture继承了Runnable和Future,并且Executor实际调用的是executor( Runnable run);也就是调用Runnable对象,但实际上FutureTask中的void run方法实际上会调用FutureTask中Callable callable属性的call()方法。是不是很晕<<<

    为什么是Callable而不是Runnable

    返回值需要进行泛型约束,来避免代码编写的强制转型。对于Callable接口增加了<V>作为返回值

    @FunctionalInterface
    public 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;
    }
    

    如果直接使用原来的Runnable进行约束的话会导致ExecutorService返回的值为Object类型,需要在代码里进行强制转化,这可能会抛出转换异常。

    所以ExecutorService中为Runnable提供了两个submit方法其中一种带有泛型

    /*带泛型*/    
    <T> Future<T> submit(Runnable task, T result);
    /*不带泛型*/
    Future<?> submit(Runnable task);
    

    Executor继承体系

    线程æ±

    Executor

    java.util.concurrent.Executor ,任务的执行者接口,线程池框架中几乎所有类都直接或者间接实现 Executor 接口,它是线程池框架的基础。

    Executor 提供了一种将“任务提交”与“任务执行”分离开来的机制,它仅提供了一个 #execute(Runnable command) 方法,用来执行已经提交的 Runnable 任务。代码如下:

    public interface Executor {
    
        void execute(Runnable command);
        
    }
    

    Executor中的四个状态

    创建(create)->提交(submit)->开始(start)->完成(finish)

    ExcutorService

    java.util.concurrent.ExcutorService ,继承 Executor 接口,它是“执行者服务”接口,它是为”执行者接口 Executor “服务而存在的。准确的地说,ExecutorService 提供了”将任务提交给执行者的接口( submit 方法)”,”让执行者执行任务( invokeAll , invokeAny 方法)”的接口等等。代码如下:

    public interface ExecutorService extends Executor {
    
        /**
         * 启动一次顺序关闭,执行以前提交的任务,但不接受新任务
         */
        void shutdown();
    
        /**
         * 试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表
         */
        List<Runnable> shutdownNow();
    
        /**
         * 如果此执行程序已关闭,则返回 true。
         */
        boolean isShutdown();
    
        /**
         * 如果关闭后所有任务都已完成,则返回 true
         */
        boolean isTerminated();
    
        /**
         * 请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行
         */
        boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException;
    
        // ========== 提交任务 ==========
    
        /**
         * 提交一个返回值的任务用于执行,返回一个表示任务的未决结果的 Future
         */
        <T> Future<T> submit(Callable<T> task);
    
        /**
         * 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
         */
        <T> Future<T> submit(Runnable task, T result);
    
        /**
         * 提交一个 Runnable 任务用于执行,并返回一个表示该任务的 Future
         */
        Future<?> submit(Runnable task);
    
        /**
         * 执行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表
         */
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;
    
        /**
         * 执行给定的任务,当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的 Future 列表
         */
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                      long timeout, TimeUnit unit)
            throws InterruptedException;
    
        /**
         * 执行给定的任务,如果某个任务已成功完成(也就是未抛出异常),则返回其结果
         */
        <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException;
    
        /**
         * 执行给定的任务,如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果
         */
        <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                        long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    

    AbstractExecutorService

    java.util.concurrent.AbstractExecutorService ,抽象类,实现 ExecutorService 接口,为其提供默认实现。

    AbstractExecutorService 除了实现 ExecutorService 接口外,还提供了 #newTaskFor(...) 方法,返回一个 RunnableFuture 对象,在运行的时候,它将调用底层可调用任务,作为 Future 任务,它将生成可调用的结果作为其结果,并为底层任务提供取消操作。

    实际上都是转化为RunnableFuture类

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

    多种常用线程池

    newFixedThreadPool

    newFixedThreadPool将创建一个固定长度的线程池,每次提交一个任务时就创建一个线程,这时线程池的规模不再改变(如果发生了未预期的Exception而结束,那么线程池会补充一个新的线程

    newCachedThreadPool

    newCachedThreadPool将创建一个可缓存的线程池,如果线程池的当前规模超过了处理需求时,那么将回收空闲的线程,当需求增加时,则可以添加新的线程,线程的规模不存在任何限制

    newScheduledThreadPool

    newFixedThreadPool

    ScheduledExecutorService

    java.util.concurrent.ScheduledExecutorService ,继承 ExecutorService ,为一个“延迟”和“定期执行”的 ExecutorService 。他提供了如下几个方法,安排任务在给定的延时执行或者周期性执行。代码如下:

    // 创建并执行在给定延迟后启用的 ScheduledFuture。
    <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
    
    // 创建并执行在给定延迟后启用的一次性操作。
    ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
    
    // 创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;
    //也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
    ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
    
    // 创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。
    ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
    
    内容来自博客园,拒绝爬虫网站
  • 相关阅读:
    并发编程的艺术
    Redis字符串实现,SDS与C的区别,空间预分配
    Jvm
    Redis数据结构的实现
    发一篇感谢身边的所有从事it工作的朋友
    BeanFactory 默认的注入实现类DefaultListableBeanFactory
    jsSwitch语句优化
    彻底搞懂 Nginx 的五大应用场景
    Spring Boot 整合 Quartz 轻松实现任务调度!
    js计算两个给定日期之间的天数
  • 原文地址:https://www.cnblogs.com/Heliner/p/10737070.html
Copyright © 2011-2022 走看看