浅谈线程池之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()方法,都可以实现有返回值的效果。

原文地址:https://www.cnblogs.com/shisanye/p/13126857.html