与数据库连接池类似,线程池在系统启动时即创建大量空闲的线程。程序将一个 Runnable 对象或 Callable 对象传给线程池,线程池就会启动一个线程来执行它们的 run() 或 call() 方法,当 run() 或 call() 方法执行结束后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个 Runnable 对象的 run() 或 call() 方法。
创建线程池
使用 Executors 工厂类来产生线程池,包含以下静态工厂方法来创建线程池:
- newCachedThreadPool():创建一个具有缓存功能的线程池,系统根据需要创建线程,这些线程将会被缓存在线程池中。
- newFixedThreadPool(int nThreads):创建一个可重用的、具有固定线程数 nThreads 的线程池。
- newSingleThreadExecutor():创建一个只有单线程的线程池,它相当于调用 newFixedThreadPool() 方法时传入参数为 1.
- newScheduledThreadPool(int corePoolSize):创建具有指定线程数的线程池,它可以在指定延迟后执行线程任务。corePoolSize 指池中所保存的线程数,即使线程是空闲的也被保存在线程池内。
- newSingleThreadScheduledExecutor():创建只有一个线程的线程池,它可以在指定延迟后执行线程任务。
- ExecutorService newWorkStealingPool(int parallelism):创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争。
- ExecutorService newWorkStealingPool():该方法是前一个方法的简化版本。如果当前机器有 4 个CPU,则目标并行级别设置为 4,也就是相当于为前一个方法传入 4 作为参数。
上面7个方法中的前三个返回一个 ExecutorService 对象,该对象代表一个线程池,它可以执行 Runnable 对象或 Callable 对象所代表的线程;而中间两个方法返回一个 ScheduledExecutorService 线程池,它是 ExecutorService 的子类,它可以在指定延迟后执行线程任务;最后两个方法则是 Java8 新增的,可以充分利用多 CPU 并行的能力,这个两个方法生成的 work stealing 池,都相当于后台线程池。
ExecutorService
ExecutorService 代表尽快执行线程的线程池(意味着只要线程池中有空闲的线程,就立即执行线程任务),程序只要将一个 Runnable 对象或 Callable 对象提交给该线程池,该线程池就会尽快执行该任务。ExecutorService 提供了如下三个方法:
- Future<?> submit(Runnable task):将一个 Runnable 对象提交给指定的线程池,线程池将在有空闲线程时执行 Runnable 对象代笔的任务。其中 Future 对象代表 Runnable 任务的返回值。可以调用 Future 的 isDone()、isCancelled() 方法来获得 Runnable 对象的执行状态。
Future :将一个 Runnable 对象提交给指定的线程,线程池将在有空闲线程时执行 Runnable 对象代表的任务。其中 result 显式指定线程执行结束后的返回值,所以 Future 对象将在 run() 方法执行结束后返回 result。submit(Runnable task,T result) Future :将一个 Callable 对象提交给指定的线程池,线程池将在有空闲线程时执行 Callable 对象代表的任务。submit(Callable task)
ScheduledExecutorService
ScheduledExecutorService 代表可在指定延迟后或周期性地执行线程任务的线程池,它提供了如下 4 个方法:
- ScheduledFuture
schedule(Callable :指定 callable 任务将在 delay 延迟后执行。callable,long delay,TimeUnit unit) - ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unie):指定 command 任务将在 delay 延迟后执行。
- ScheduledFuture<?> schedulAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit):指定 command 任务将在 delay 延迟后执行,而且以设定频率重复执行。在 initialDelay 后开始执行,依次在 initialDelay+period、initialDelay+2*period…..处重复执行,以此类推。
- ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit):创建并执行一个在给定延迟后首次启用的定期操作,随后在每一次执行终止和下一次执行开始之间都存在给定的延迟。如果任务在任一次执行时遇到异常,就会取消后续执行;否则,只能通过程序来显式取消或终止该任务。
用完一个线程池后,应该调用该线程池的 shutdown() 方法,来启动该线程池的关闭序列,此时线程池不再接收新任务,但会将以前提交的任务执行完成后所有线程死亡。也可以调用线程池的 shutdownNow() 方法来立即线程池。
使用线程池
使用线程池来执行线程任务的步骤如下:
- 调用 Executors 工具类的静态工厂方法来创建一个 ExecutorService 对象,该对象代表一个线程池。
- 创建 Runnable 实现类或 Callable 实现类的实例,在 run() 或 call() 方法中编写执行任务。
- 调用 ExecutorService 对象的 submit() 方法来提交 Runnable 实例或 Callable 实例。
- 当不想提交任何任务似乎,调用 ExecutorService 对象的 shutdown() 方法来关闭线程池。