Executor和ExecutorService区别?
Executor和ExecutorService都是Java并发编程中的重要概念,两者都用于异步地执行任务,但是它们之间存在一些重要的区别:
- 设计目标:
- Executor:设计目标是提供一个简单的、统一的、高层次的抽象来执行命令,Executor框架主要用于简化线程管理,包括启动、调度和终止线程。
- ExecutorService:设计目标是提供一个更全面的框架,用于管理和控制大量并发的任务,它扩展了Executor接口,提供了更多高级功能,如任务提交、关闭、定期执行等。
- 生命周期管理:
- Executor:没有内置的生命周期管理功能,当提交一个命令时,Executor会立即启动一个新的线程(如果需要),如果想在某个时间点停止执行命令,需要手动实现这一功能。
- ExecutorService:提供了内置的生命周期管理功能,可以使用
shutdown()
或shutdownNow()
方法来停止接受新的任务并关闭ExecutorService,已经提交的任务会继续执行,直到完成。
- 任务提交:
- Executor:通过实现Runnable或Callable接口的任务对象来提交任务,Executor没有提供任务结果的处理方式。
- ExecutorService:提供了Future和Callable接口的任务提交方式,Future接口使得任务执行者能够异步地获取任务结果。
- 异常处理:
- Executor:没有提供异常处理机制,如果任务抛出未捕获的异常,那么这个异常会被传递给UncaughtExceptionHandler,由系统默认处理。
- ExecutorService:允许通过Future的get()方法获取任务的执行结果,如果任务抛出异常,get()方法会抛出ExecutionException,可以通过ExecutionException的getCause()方法获取原始的异常。
- 线程池:
- Executor:没有内置的线程池功能,如果需要使用线程池,需要自己创建并管理线程池。
- ExecutorService:是线程池的一种实现方式,它内部封装了一个线程池,通过调用
shutdown()
或shutdownNow()
方法可以关闭线程池。
- 并行流:
- Executor:不是并行流的底层实现,并行流使用的是ForkJoinPool,而不是Executor或ExecutorService。
- ExecutorService:可以作为并行流的底层实现,通过将Stream的中间操作和终止操作组合在一起,可以充分利用ExecutorService的并发能力。
- 适用场景:
- Executor:适用于简单的异步任务执行场景,例如启动一个新线程来执行一个简单的计算任务,由于没有生命周期管理、任务结果处理等功能,Executor在复杂的多任务并发场景中可能不够用。
- ExecutorService:适用于需要管理大量并发任务、生命周期管理、任务结果处理等功能的场景,例如Web服务器接受客户端请求并处理请求。
总结,Executor是一个相对简单的框架,适用于简单的异步任务执行场景;而ExecutorService提供了更全面的功能,适用于复杂的并发任务管理场景。在实际应用中,通常会使用ExecutorService而不是Executor,因为ExecutorService提供了更多的功能和更好的性能。
使用Executor
下面代码是Executor来执行一个线程,如下:
import java.util.concurrent.Executor;
public class SimpleExecutor implements Executor {
@Override
public void execute(Runnable command) {
new Thread(command).start();
}
}
public class Main {
public static void main(String[] args) {
SimpleExecutor executor = new SimpleExecutor();
executor.execute(() -> System.out.println("Task running in a new thread: " + Thread.currentThread().getName()));
}
}
使用ExecutorService
下面代码是ExecutorService
来执行一个线程,如下:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceExample {
public static void main(String[] args) {
// 创建一个单线程的ExecutorService
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 提交任务
executorService.submit(() -> {
System.out.println("Task is running in thread: " + Thread.currentThread().getName());
});
}
}