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