线程池学习(二)execute() 和 submit() 的区别
发布人:shili8
发布时间:2025-01-11 22:25
阅读次数:0
**线程池学习(二)**
在上一篇文章中,我们已经了解了线程池的基本概念、创建线程池的方法以及线程池的使用。今天我们将继续讨论线程池中的两个重要方法:`execute()` 和 `submit()`. 这两个方法都是用于执行任务的,但它们有着不同的设计理念和使用场景。
### execute()
`execute()` 方法是线程池中最早出现的一个方法,它用于直接执行一个Runnable或Callable对象。这个方法非常简单,仅仅是将任务放入到线程池中,然后由线程池内部的线程来执行。
javapublic void execute(Runnable command) { if (command == null) throw new NullPointerException(); // 将任务放入到线程池中 addTask(command); }
在上面的代码中,我们可以看到`execute()`方法首先检查传入的Runnable或Callable对象是否为null,如果是则抛出一个NullPointerException. 然后,它将任务放入到线程池中,具体来说就是调用了`addTask()`方法。
### submit()
`submit()` 方法也是用于执行一个Runnable或Callable对象,但它比 `execute()` 方法更强大。这个方法不仅可以直接执行任务,还可以返回一个Future对象,这个Future对象代表了任务的执行结果。
javapublic Future> submit(Runnable task) { if (task == null) throw new NullPointerException(); // 将任务放入到线程池中 RunnableInfo r = SynchronousQueue.enqueue(task); int c = availableProcessors(); for (int i =0; i < Math.min(c, _common.poolSize); i++) internalAdd(r); return r; } publicFuture submit(Callable task) { if (task == null) throw new NullPointerException(); // 将任务放入到线程池中 RunnableFuture f = SynchronousQueue.enqueue(task); int c = availableProcessors(); for (int i =0; i < Math.min(c, _common.poolSize); i++) internalAdd(f); return f; }
在上面的代码中,我们可以看到`submit()`方法有两个重载版本,一个用于Runnable对象,另一个用于Callable对象。无论哪种情况,它们都会将任务放入到线程池中,然后返回一个Future对象。
### execute() 和 submit() 的区别虽然 `execute()` 和 `submit()` 都是用于执行任务的,但它们有着不同的设计理念和使用场景。
* `execute()` 方法直接执行一个Runnable或Callable对象,而不返回任何结果。
* `submit()` 方法不仅可以直接执行任务,还可以返回一个Future对象,这个Future对象代表了任务的执行结果。
在大多数情况下,`submit()` 方法比 `execute()` 方法更合适,因为它提供了更多的灵活性和控制权。然而,在某些特定场景中,`execute()` 方法可能是更好的选择。
### 总结线程池中的 `execute()` 和 `submit()` 方法都是用于执行任务的,但它们有着不同的设计理念和使用场景。`execute()` 方法直接执行一个Runnable或Callable对象,而不返回任何结果。`submit()` 方法不仅可以直接执行任务,还可以返回一个Future对象,这个Future对象代表了任务的执行结果。在大多数情况下,`submit()` 方法比 `execute()` 方法更合适,因为它提供了更多的灵活性和控制权。
### 示例代码
javaimport java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { // 创建一个线程池 ExecutorService executor = Executors.newFixedThreadPool(5); // 使用execute()方法执行任务 Runnable task1 = new Task("Task1"); executor.execute(task1); // 使用submit()方法执行任务并获取Future对象 Runnable task2 = new Task("Task2"); Future> future = executor.submit(task2); try { System.out.println(future.get()); } catch (Exception e) { e.printStackTrace(); } // 关闭线程池 executor.shutdown(); } } class Task implements Runnable { private String name; public Task(String name) { this.name = name; } @Override public void run() { System.out.println("Executing task: " + name); } }
在上面的示例代码中,我们创建了一个线程池,然后使用 `execute()` 方法执行一个任务。接着,我们使用 `submit()` 方法执行另一个任务,并获取Future对象。最后,我们关闭线程池。
### 注释* 在这个示例代码中,我们使用了`Executors.newFixedThreadPool(5)`方法创建了一个固定大小的线程池,大小为5。
* 我们使用`executor.execute(task1)`方法执行第一个任务,然后使用`executor.submit(task2)`方法执行第二个任务,并获取Future对象。
* 最后,我们关闭线程池以释放系统资源。
这个示例代码演示了如何使用 `execute()` 和 `submit()` 方法执行任务,以及如何获取Future对象来代表任务的执行结果。