Java中异步处理任务时,我们通常都会定义线程池来执行任务。然而执行的方式通常主要有两种:
1.直接调用execute方法。
2.调用submit方法,再用Future去get获取执行结果。
这两种方法分别有怎样的区别呢?
我们翻阅Jdk源码则可发现在Executer类中已有定义execute方法如下:
- 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);
- }
即execute方法可以支持实现了Runnable接口的任务。而我们常用的ExecutorService与Executer的为继承关系。
从上图信息可以看出ExecutorService中定义submit方法的时候通过重载的方式实现了三个方法,分别可以看出来支持实现了Callable接口的任务、支持实现了Runnable接口的任务。再看关于submit方法定义的描述信息:
-
- /**
- * Submits a value-returning task for execution and returns a
- * Future representing the pending results of the task. The
- * Future's {@code get} method will return the task's result upon
- * successful completion.
- *
- * <p>
- * If you would like to immediately block waiting
- * for a task, you can use constructions of the form
- * {@code result = exec.submit(aCallable).get();}
- *
- * <p>Note: The {@link Executors} class includes a set of methods
- * that can convert some other common closure-like objects,
- * for example, {@link java.security.PrivilegedAction} to
- * {@link Callable} form so they can be submitted.
- *
- * @param task the task to submit
- * @param <T> the type of the task's 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(Callable<T> task);
-
- /**
- * 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);
-
- /**
- * Submits a Runnable task for execution and returns a Future
- * representing that task. The Future's {@code get} method will
- * return {@code null} upon <em>successful</em> completion.
- *
- * @param task the task to submit
- * @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
- */
- Future<?> submit(Runnable task);
但从上面两端源码关于方法的注释上即可得出如下的结论。
1.从支持方面来分析,execute()只能执行实现Runnable接口类型的任务;而submit()不仅可以执实现Runnable类型接口的任务,也可以执行实现Callable接口类型的任务。
2.从返回结果来分析,execute()没有返回值,而submit()有在添加Callable类型任务的时候有返回值,我们一般通过返回值查看线程执行情况。这样以来,execute更多的是应用于不关注结果的异步执行场景,而submit则倾向于异步计算任务的场景。
3.从异常处理来分析,submit可以通过Future.get()方法抛出异常,方便我们自定义异常处理;而execute()会终止异常,没有返回值。