淺談線程池之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()方法,都可以實現有返回值的效果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM