转:http://blog.csdn.net/peachpi/article/details/6771946
因为之前一直是用的execute方法,最近有个情况需要用到submit方法,所以研究了下。
三个区别:
1、接收的参数不一样
2、submit有返回值,而execute没有
Method submit extends base method Executor.execute by creating and returning a Future that can be used to cancel execution and/or wait for completion.
用到返回值的例子,比如说我有很多个做validation的task,我希望所有的task执行完,然后每个task告诉我它的执行结果,是成功还是失败,如果是失败,原因是什么。然后我就可以把所有失败的原因综合起来发给调用者。
个人觉得cancel execution这个用处不大,很少有需要去取消执行的。
而最大的用处应该是第二点。
3、submit方便Exception处理
There is a difference when looking at exception handling. If your tasks throws an exception and if it was submitted with execute
this exception will go to the uncaught exception handler (when you don't have provided one explicitly, the default one will just print the stack trace to System.err
). If you submitted the task with submit
any thrown exception, checked or not, is then part of the task's return status. For a task that was submitted with submit
and that terminates with an exception, the Future.get
will rethrow this exception, wrapped in an ExecutionException
.
意思就是如果你在你的task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过捕获Future.get抛出的异常。
比如说,我有很多更新各种数据的task,我希望如果其中一个task失败,其它的task就不需要执行了。那我就需要catch Future.get抛出的异常,然后终止其它task的执行,代码如下:
51cto上有一篇非常好的文章“Java5并发学习”(http://lavasoft.blog.51cto.com/62575/115112),下面的代码是基于它之上修改的。
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Random;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- public class ExecutorServiceTest {
- public static void main(String[] args) {
- ExecutorService executorService = Executors.newCachedThreadPool();
- List<Future<String>> resultList = new ArrayList<Future<String>>();
- // 创建10个任务并执行
- for (int i = 0; i < 10; i++) {
- // 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
- Future<String> future = executorService.submit(new TaskWithResult(i));
- // 将任务执行结果存储到List中
- resultList.add(future);
- }
- executorService.shutdown();
- // 遍历任务的结果
- for (Future<String> fs : resultList) {
- try {
- System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- executorService.shutdownNow();
- e.printStackTrace();
- return;
- }
- }
- }
- }
- class TaskWithResult implements Callable<String> {
- private int id;
- public TaskWithResult(int id) {
- this.id = id;
- }
- /**
- * 任务的具体过程,一旦任务传给ExecutorService的submit方法,则该方法自动在一个线程上执行。
- *
- * @return
- * @throws Exception
- */
- public String call() throws Exception {
- System.out.println("call()方法被自动调用,干活!!! " + Thread.currentThread().getName());
- if (new Random().nextBoolean())
- throw new TaskException("Meet error in task." + Thread.currentThread().getName());
- // 一个模拟耗时的操作
- for (int i = 999999999; i > 0; i--)
- ;
- return "call()方法被自动调用,任务的结果是:" + id + " " + Thread.currentThread().getName();
- }
- }
- class TaskException extends Exception {
- public TaskException(String message) {
- super(message);
- }
- }
执行的结果类似于:
- call()方法被自动调用,干活!!! pool-1-thread-1
- call()方法被自动调用,干活!!! pool-1-thread-2
- call()方法被自动调用,干活!!! pool-1-thread-3
- call()方法被自动调用,干活!!! pool-1-thread-5
- call()方法被自动调用,干活!!! pool-1-thread-7
- call()方法被自动调用,干活!!! pool-1-thread-4
- call()方法被自动调用,干活!!! pool-1-thread-6
- call()方法被自动调用,干活!!! pool-1-thread-7
- call()方法被自动调用,干活!!! pool-1-thread-5
- call()方法被自动调用,干活!!! pool-1-thread-8
- call()方法被自动调用,任务的结果是:0 pool-1-thread-1
- call()方法被自动调用,任务的结果是:1 pool-1-thread-2
- java.util.concurrent.ExecutionException: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
- at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
- at java.util.concurrent.FutureTask.get(FutureTask.java:83)
- at com.cicc.pts.ExecutorServiceTest.main(ExecutorServiceTest.java:29)
- Caused by: com.cicc.pts.TaskException: Meet error in task.pool-1-thread-3
- at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:57)
- at com.cicc.pts.TaskWithResult.call(ExecutorServiceTest.java:1)
- at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
- at java.util.concurrent.FutureTask.run(FutureTask.java:138)
- at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
- at java.lang.Thread.run(Thread.java:619)
可以看见一旦某个task出错,其它的task就停止执行。
相关推荐
`ExecutorService`通过`execute()`和`submit()`这两个方法来提交任务进行执行。理解并熟练运用这两个方法对于优化并发性能至关重要。 `execute()`方法: `execute(Runnable command)`是`ExecutorService`最基础的...
### 线程池的submit和execute方法的区别详解 #### 一、引言 线程池作为Java并发编程中的一项关键技术,在实现高效并发任务管理方面发挥着重要作用。而在实际开发中,开发者经常会遇到两种用于向线程池提交任务的...
例如,对于`ExecutorService es`,执行`submit()`方法时,内部会将`Runnable`或`Callable`包装成`RunnableFuture`实例,如`FutureTask`。`ExecutorService`执行这个`RunnableFuture`,任务完成后,结果可通过`Future...
execute() 方法用于执行给定的 Runnable 任务,它是提交任务的基础方法,submit() 实际上也是通过 execute() 来执行任务的。 总结来说,ExecutorService 是 Java 并发编程的重要组件,它提供了一套完善的机制来管理...
【Executor、Executors和ExecutorService详解】 在Java并发编程中,`Executor`、`Executors`和`ExecutorService`是核心组件,它们帮助开发者高效管理线程资源,提高程序的并发性能。理解这三个概念的区别和用途是...
2. **提交任务**:使用`execute(Runnable task)`方法提交Runnable任务,或者使用`submit(Callable<T> task)`提交Callable任务并获取Future结果。 3. **关闭线程池**:任务执行完毕后,应调用`shutdown()`或`shutdown...
此外,ExecutorService的submit()方法返回一个Future对象,可以用来检查任务的状态(是否完成)、获取结果或取消任务。 ExecutorService的主要方法包括: - `execute(Runnable)`:异步执行Runnable任务。 - `submit...
在 Executor 接口中,只定义了 execute 方法,而 submit 方法则是在 ExecutorService 接口中定义的。 ```java public interface ExecutorService extends Executor { ... <T> Future<T> submit(Callable<T> task)...
首先,我们需要了解 ExecutorService 的两个关闭方法:shutdown() 和 shutdownNow()。这两个方法的区别在于它们的安全性和响应性。shutdown() 方法会正常关闭线程池,等待所有任务执行完毕后关闭,而 shutdownNow() ...
ExecutorService则提供了更丰富的操作,如shutdown()用于停止接收新任务并等待已提交任务完成,shutdownNow()尝试停止所有正在执行的任务,以及submit()方法用于提交Callable任务并返回Future结果。 3. Executors...
例如,使用`ExecutorService.submit(Callable)`或`ExecutorService.submit(Runnable)`方法,会返回一个`Future`对象,可以用来检查任务状态、取消任务或获取结果。 总的来说,Java的Executor框架通过引入线程池和...
在编程中,我们有多种方法来创建和管理线程。以下是对这些方法的详细阐述,适合初学者理解。 1. 继承Thread类: 在Java中,最常见的方式是继承`java.lang.Thread`类并重写它的`run()`方法。当你调用`start()`方法时...
* ExecutorService 接口:提供了 execute() 方法、shutdown() 方法和 submit() 方法,用于执行 Runnable 任务和管理线程池。 * ThreadPoolExecutor 类:是一个线程池执行器,提供了一个固定大小的线程池。 Callable...
2. **ExecutorService接口**:继承自Executor接口,增加了管理和控制线程池的功能,如`submit()`用于提交任务,`shutdown()`用于关闭线程池,`shutdownNow()`用于尝试停止所有正在执行的任务等。 3. **...
- `execute(Runnable task)`:用于执行给定的Runnable任务,这是`Executor`接口中唯一的方法,但`ExecutorService`提供了更高级的控制。 - `submit(Callable<T> task)`:提交一个Callable任务,返回一个Future表示...
JDK线程池是Java中的一个内置线程池实现,它提供了一个ExecutorService接口,该接口提供了execute、submit、shutdown等方法来管理线程池。JDK线程池可以通过ThreadPoolExecutor类来创建,ThreadPoolExecutor类提供了...
线程池中重要的方法包括execute()、submit()、shutdown()、shutdownNow()、isTerminated()和isShutdown()等。execute()方法用于执行Runnable任务;submit()方法可以用来提交Callable或Runnable任务,并返回一个...
4. 使用线程池,如ExecutorService,通过submit()或execute()方法执行Runnable或Callable任务。 线程的生命周期包括创建、就绪、运行、阻塞和死亡五个阶段。创建后调用start()方法使其变为就绪,然后由线程调度器...
* AbstractExecutorService是Java中的抽象线程池类,提供了execute()和submit()方法的默认实现。 七、高并发编程的其他知识点 * volatile关键字可以确保变量的可见性和原子性。 * synchronized关键字可以确保方法...
基于`Executor`,`ExecutorService`接口提供了更丰富的功能,如关闭线程池的`shutdown()`和`shutdownNow()`方法,以及管理和控制任务执行的方法,如`submit()`、`invokeAll()`和`invokeAny()`。`ExecutorService`...