Java 中 Executor 和 Executors 都是与多线程开发相关的类,它们在管理线程池中的线程方面都有一定的作用。虽然很相似,但其主要区别如下:
Executor
1、Executor 是一个基础接口。它服从线程池和任务队列的分离原则,提供了一个简单、标准的方法来执行 Runnable 对象的任务,可以让实现者自己选择队列类型,并通过指定线程的调度策略、创建一个全新的线程或重复使用已有的线程来调整线程数目,以满足应用程序获得最优吞吐量。
2、Executor 的核心思想结合可扩展性设计,您可以面向抽象接口编写代码,从而充分利用多个线程之间的竞争和协作。对于分批处理的操作,你不用等待某个操作完成后再启动另一个操作;只需盯着那个‘工作时间表’即可。
3、Executor 缺点是需要手动创建线程池,如果没有正确配置线程池大小和任务队列的长度,则会导致线程阻塞或太多的 CPU 资源消耗。这意味着如果不能正确地使用 Executor 类,那么将极大的影响应用程序的运行效率。 而且线程数量和生命周期控制等不是很方便。
Executors
1、Executors 是一个工厂方法类,提供了一些静态工厂方法用于创建线程池、提供常用的任务队列实现,并包括很好的限流策略,可以大大减少编码工作量。它为异步计算提供了更友好、方便的访问方式。
2、Executors 支持定时执行以及延迟执行、递归查询(CompletionService)、并发任务完成和快捷创建固定大小的线程池等多种方式来简化线程池的创建问题和ScheduleExecutorService沟通问题;另外 Executors 还支持从任务队列中获取已经处理完的结果;
3、Executors 的弊端是可能会清除 ThreadPoolExecutor 中的意外事故。开发者在使用过程中需要谨慎,目前Java 11对老版本的 Executor.xxx()进行了废弃处理,并提出要尽力使用ThreadPoolExecutor构造方法,或newCachedThreadPool, newFixedThreadPool, newWorkStealingPool 等专用方法。
总的来说,Executor 和 Executors 是两种不同的多线程机制,即接口之一与实现的区别:以Executor 类为基础,Executors 功能更加丰富。它们都可用于管理线程池中的多个线程,但如果想要更具灵活性的高级线程控制和错误处理选项,则需要使用一个实现了 Executor 接口的 ThreadPoolExecutor 或 ScheduledThreadPoolExecutor。
虽然 Executors 是一个工厂方法类,提供了一些静态工厂方法用于创建线程池,但是需要谨慎。因为Executors 还存在一些缺点,在极端情况下,会导致一些意外事故和性能问题。对于线程池的细节和管理控制需求比较高的开发人员,建议直接使用 ThreadPoolExecutor。
Executor 是一个实现多线程设计的接口,其重要作用是通过队列排程来执行任务并防止资源耗尽;Executor 的缺点是手动调整线程池的大小和任务队列的长度比较麻烦;Executors为开发者提供了方便的创建线程池、常见队列实现和限流策略等,从而支持定时执行和其他常用任务类型,并且支持从任务队列中获取处理后的结果等;另外虽然 Executors 提供了许多简便功能,与 ThreadPoolExecutor 相比,Executors 仍然具有一些不同,包括可能出现的异常抛出、过度消耗 CPU 资源、线程数量和生命周期控制等问题。