executor经常会使用到,这里主要比较一下execute和submit方法的区别。
这个两个方法最主要的区别是如果runable中的方法抛出异常,execute会终止这个线程。而submit 不会。
这里分析一下原因。
测试代码:
ExecutorService es = Executors.newCachedThreadPool(namedThreadFactory); try { es.submit(new Runnable() { @Override public void run() { System.out.println("ok"); throw new RuntimeException(); } }); } catch (Exception e) { System.out.println(e.getMessage()); } System.out.println("end");
其实两种方法提交给ThreadPoolExecutor执行的主要逻辑都是一致的,在ThreadPoolExecutor$Worker.run()中被执行,ThreadPoolExecutor$Worker是一个工作线程,每个Worker对象对应了一个线程, t会被调用start()。
private Thread addThread(Runnable firstTask) { Worker w = new Worker(firstTask); Thread t = threadFactory.newThread(w); if (t != null) { w.thread = t; workers.add(w); int nt = ++poolSize; if (nt > largestPoolSize) largestPoolSize = nt; } return t; }
ThreadPoolExecutor$Worker.run(): Runnable task = firstTask; firstTask = null; while (task != null || (task = getTask()) != null) { runTask(task); task = null; }
注意如果没有没有任务,getTask会阻塞,然后都会执行runTask。 主要区别在于task对象的不同,sumit的task对象是FutureTask,而execute是一个普通的Runable。这里可以看到如果是Runable被执行调用run会抛出异常的,线程被中断。
runTask(Runnable task): boolean ran = false; beforeExecute(thread, task); try { task.run(); ran = true; afterExecute(task, null); ++completedTasks; } catch (RuntimeException ex) { if (!ran) afterExecute(task, ex); throw ex; }
如果是FutureTask
void innerRun(): try { runner = Thread.currentThread(); if (getState() == RUNNING) innerSet(callable.call()); else releaseShared(0); } catch (Throwable ex) { innerSetException(ex); }
Thread [Action-thread-0] ThreadPoolExecutor$Worker.runTask(Runnable) line: 886 ThreadPoolExecutor$Worker.run() line: 908 [local variables unavailable] Thread.run() line: 662 Thread [Action-thread-0] FutureTask$Sync.innerRun() line: 306 [local variables unavailable] FutureTask<V>.run() line: 138 [local variables unavailable] ThreadPoolExecutor$Worker.runTask(Runnable) line: 886 ThreadPoolExecutor$Worker.run() line: 908 [local variables unavailable] Thread.run() line: 662
相关推荐
`ExecutorService`通过`execute()`和`submit()`这两个方法来提交任务进行执行。理解并熟练运用这两个方法对于优化并发性能至关重要。 `execute()`方法: `execute(Runnable command)`是`ExecutorService`最基础的...
### 线程池的submit和execute方法的区别详解 #### 一、引言 线程池作为Java并发编程中的一项关键技术,在实现高效并发任务管理方面发挥着重要作用。而在实际开发中,开发者经常会遇到两种用于向线程池提交任务的...
基于`Executor`,`ExecutorService`接口提供了更丰富的功能,如关闭线程池的`shutdown()`和`shutdownNow()`方法,以及管理和控制任务执行的方法,如`submit()`、`invokeAll()`和`invokeAny()`。`ExecutorService`...
`Executor`是Java线程池的顶级接口,它只有一个方法`execute(Runnable command)`,用于执行传入的任务。`Executor`并不直接创建线程,而是通过实现它的子接口或类来完成。通常,我们不会直接使用`Executor`,而是...
- **任务执行**:核心接口`Executor`定义了任务的执行方法`execute()`,用于启动一个任务。`ExecutorService`接口继承自`Executor`,提供了更丰富的管理功能,如关闭线程池、管理线程等。`ThreadPoolExecutor`和`...
线程池中重要的方法包括execute()、submit()、shutdown()、shutdownNow()、isTerminated()和isShutdown()等。execute()方法用于执行Runnable任务;submit()方法可以用来提交Callable或Runnable任务,并返回一个...
Java并发编程中的Executor、Executors和ExecutorService是Java并发编程框架的重要组成部分,它们为开发者提供了高效管理和控制线程执行的工具。以下是对这些概念的详细解释: 1. Executor: Executor是一个接口,它...
Executor框架的核心接口是`Executor`,它只有一个方法`execute(Runnable command)`,用于执行给定的任务。`Executor`接口提供了任务执行的基本模型,但并未提供关闭或管理线程池的能力。 为了解决这个问题,`...
在 Executor 接口中,只定义了 execute 方法,而 submit 方法则是在 ExecutorService 接口中定义的。 ```java public interface ExecutorService extends Executor { ... <T> Future<T> submit(Callable<T> task)...
- 使用`submit(Callable)`方法提交Callable任务并获取结果。 #### 代码示例:提交Runnable任务 ```java executor.execute(() -> { System.out.println("Task running in thread: " + Thread.currentThread()....
真正实现线程池功能的是ExecutorService接口,它是Executor的子接口,提供了更多的管理和控制线程池的方法,如`shutdown()`和`submit()`等。 Executors类是一个工厂类,提供了一系列静态方法,用于创建不同类型的...
execute() 方法用于执行给定的 Runnable 任务,它是提交任务的基础方法,submit() 实际上也是通过 execute() 来执行任务的。 总结来说,ExecutorService 是 Java 并发编程的重要组件,它提供了一套完善的机制来管理...
`Future`接口提供了对异步计算结果的访问和控制,而`FutureTask`是`Future`的一个具体实现,它还同时实现了`Runnable`接口,因此可以直接提交给`Executor`执行。 `Future`接口提供了以下方法: 1. `boolean cancel...
Future<Integer> future = executor.submit(new Callable() { public Integer call() throws Exception { return calculateSomething(); } }); // 获取结果 Integer result = future.get(); ``` 5. Lambda表达式...
* ExecutorService 接口:提供了 execute() 方法、shutdown() 方法和 submit() 方法,用于执行 Runnable 任务和管理线程池。 * ThreadPoolExecutor 类:是一个线程池执行器,提供了一个固定大小的线程池。 Callable...
executor.execute(new Runnable() { public void run() { // 线程执行的任务 } }); } executor.shutdown(); // 关闭线程池 ``` 4. **使用Future和Callable** `Callable`接口类似于`Runnable`,但其`call...
2. **ExecutorService接口**:继承自Executor接口,增加了管理和控制线程池的功能,如`submit()`用于提交任务,`shutdown()`用于关闭线程池,`shutdownNow()`用于尝试停止所有正在执行的任务等。 3. **...
这个框架的核心是 `Executor` 接口,它定义了一个单一的方法 `execute()`,用于提交 `Runnable` 或 `Callable` 任务。 在传统的并发编程中,我们通常会直接使用 `Thread` 类来创建和启动线程,如 `...
- **ExecutorService**: Executor的一个子接口,增加了管理和控制线程池的方法,如`shutdown()`和`submit()`。 - **Thread Pool**: 线程池是一种线程复用机制,可以预先创建一定数量的线程,当任务到来时,从池中...
然后,通过`ExecutorService`的`submit()`方法提交这个任务,它会在新的线程中运行。这种方式不会返回结果,适用于无需等待任务完成的情况。 示例代码: ```java ExecutorService executor = Executors....