• 浅谈线程池之submit方法和execute方法


    1.首先说一下ExecutorService和Executor有什么区别,ExecutorService 是一个接口,它继承自Executor接口,所以ExecutorService使用Executor里面的方法

    2.execute方法是Executor接口里面的方法,不是ExecutorService接口里的方法,如果如果使用execute方法的话,其实是调用其父类的方法。

    Executor接口只有一个execute方法,并且是没有返回值的,并且只接受Runnable,不接受Callable

    public interface Executor {
    
        /**
         * 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
         */
        void execute(Runnable command);
    }
    ExecutorService接口是没有execute方法的,所以平时我们创建线程池使用的execute方法其实是其父类的方法,ExecutorService里重载里三个submit方法
    public interface ExecutorService extends Executor {

    void shutdown();


    List<Runnable> shutdownNow();


    boolean isShutdown();


    boolean isTerminated();


    boolean awaitTermination(long timeout, TimeUnit unit)
    throws InterruptedException;


    <T> Future<T> submit(Callable<T> task);


    <T> Future<T> submit(Runnable task, T result);


    Future<?> submit(Runnable task);


    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
    throws InterruptedException;


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

    3.submit方法:首先我们知道Callable是有返回值的,Runnable是没有返回值的,但是我们一般使用线程池都会想要知道这个线程的执行情况,Callbale使用线程池结合Future可以获取线程运行的情况,其实线程池使用Runnable也是可以有返回值的

    submit重载里三个方法,

    我们先来看第一个submit()方法

     <T> Future<T> submit(Callable<T> task);

    返回值是一个泛型,形参是实现了Callable的类,我们来看一下 他具体的方法,具体的方法在AbstractExecutorService类里面,AbstractExecutorService类是ExecutorService的实现类。

     1 /**
     2      * @throws RejectedExecutionException {@inheritDoc}
     3      * @throws NullPointerException       {@inheritDoc}
     4      */
     5     public <T> Future<T> submit(Callable<T> task) {
     6         if (task == null) throw new NullPointerException();
     7         RunnableFuture<T> ftask = newTaskFor(task);
     8         execute(ftask);
     9         return ftask;
    10     }

    第八行,其实submit方法到归根到底还是走的execute方法。

    我们来看下第二个submit()方法

     1 /**
     2      * Submits a Runnable task for execution and returns a Future
     3      * representing that task. The Future's {@code get} method will
     4      * return {@code null} upon <em>successful</em> completion.
     5      *
     6      * @param task the task to submit
     7      * @return a Future representing pending completion of the task
     8      * @throws RejectedExecutionException if the task cannot be
     9      *         scheduled for execution
    10      * @throws NullPointerException if the task is null
    11      */
    12     Future<?> submit(Runnable task);

    这个submit()方法的形参是实现里Runnable的类,但是他是有返回值的,返回值是Future

    下面是他的实现类

     1   /**
     2      * @throws RejectedExecutionException {@inheritDoc}
     3      * @throws NullPointerException       {@inheritDoc}
     4      */
     5     public Future<?> submit(Runnable task) {
     6         if (task == null) throw new NullPointerException();
     7         RunnableFuture<Void> ftask = newTaskFor(task, null);
     8         execute(ftask);
     9         return ftask;
    10     }

    第七行的方法,其实还是把Runnable转化成Callable了

     1 /**
     2      * Creates a {@code FutureTask} that will, upon running, execute the
     3      * given {@code Runnable}, and arrange that {@code get} will return the
     4      * given result on successful completion.
     5      *
     6      * @param runnable the runnable task
     7      * @param result the result to return on successful completion. If
     8      * you don't need a particular result, consider using
     9      * constructions of the form:
    10      * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
    11      * @throws NullPointerException if the runnable is null
    12      */
    13     public FutureTask(Runnable runnable, V result) {
    14         this.callable = Executors.callable(runnable, result);
    15         this.state = NEW;       // ensure visibility of callable
    16     }

    如果传递进来的方法是Runnable的话,这里会把Runnable转化成Callable,用的是Executors里面的方法

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

    好,回到submit方法,第三行依然走的是executor方法。

    第三种submit()方法

      /**
         * Submits a Runnable task for execution and returns a Future
         * representing that task. The Future's {@code get} method will
         * return the given result upon successful completion.
         *
         * @param task the task to submit
         * @param result the result to return
         * @param <T> the type of the result
         * @return a Future representing pending completion of the task
         * @throws RejectedExecutionException if the task cannot be
         *         scheduled for execution
         * @throws NullPointerException if the task is null
         */
        <T> Future<T> submit(Runnable task, T result);
      /**
         * @throws RejectedExecutionException {@inheritDoc}
         * @throws NullPointerException       {@inheritDoc}
         */
        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;
        }

    这种submit()使用泛型的result把返回值返回回去,这种底层还是把Runnable方法转换成Callable

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

    所以不管是Runnable还是Callable,只要使用线程池的submit()方法,都可以实现有返回值的效果。

  • 相关阅读:
    从原理层面掌握@InitBinder的使用【享学Spring MVC】
    array详解
    forward_list详解
    list详解
    deque详解
    vector详讲(三)实例
    vector详讲(二)迭代器
    vector详讲(一)
    numeric_limits<>函数
    seek()和tell()在文件里转移
  • 原文地址:https://www.cnblogs.com/shisanye/p/13126857.html
Copyright © 2020-2023  润新知