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