Java线程池是一种管理线程的机制,它可以有效地控制并发执行的线程数量,提高程序的性能和稳定性。本文将介绍Java线程池的概念、实现原理以及一个简单的示例代码。
一、Java线程池概念
线程池的作用:线程池可以预先创建一定数量的线程,当有任务需要执行时,从线程池中获取一个空闲的线程来执行任务,任务执行完毕后,将线程归还给线程池。这样可以避免频繁地创建和销毁线程,提高系统的性能。
线程池的优点:
提高系统性能:通过复用线程,减少了线程创建和销毁的开销。
控制并发数:通过限制线程池中的线程数量,可以有效地控制并发执行的线程数量,避免过多的线程导致系统资源耗尽。
提高响应速度:由于线程池中的线程已经预先创建好,所以在接收到任务时可以直接使用,无需等待线程创建完成。
二、Java线程池实现原理
Java线程池主要由以下几个部分组成:
核心线程数(corePoolSize):线程池中始终保持的线程数量。当任务队列已满且有新任务到来时,会创建新的线程来执行任务,直到达到核心线程数上限时,后续的任务将被放入阻塞队列中等待执行。
最大线程数(maximumPoolSize):线程池允许的最大线程数量。当阻塞队列已满且有新任务到来时,如果核心线程数已达到最大值,那么新任务将会被放入拒绝队列中。
工作队列(workQueue):用于存放等待执行的任务的阻塞队列。常用的阻塞队列有ArrayBlockingQueue、LinkedBlockingQueue等。
拒绝策略(rejectedExecutionHandler):当阻塞队列已满且无法创建新线程时,如何处理新任务的方法。常用的拒绝策略有AbortPolicy(抛出异常)、DiscardPolicy(丢弃任务)和CallerRunsPolicy(让调用者自己执行任务)。
线程工厂(threadFactory):用于创建新线程的工厂类。可以通过自定义线程工厂为每个新创建的线程设置一些属性,如名称、优先级等。
三、Java线程池示例代码
Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。
Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序。
Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池。
Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池。
Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执行顺序不确定)【JDK 1.8 添加】。
ThreadPoolExecutor:手动创建线程池的方式,它创建时最多可以设置 7 个参数。
下面是Java线程池示例代码:
以下是各种创建线程池的示例代码:
以下是各种创建线程池的示例代码:
- 创建一个固定大小的线程池:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5); fixedThreadPool.execute(() -> System.out.println("Hello, world!")); fixedThreadPool.shutdown(); // 必须调用 shutdown() 才能关闭线程池。否则会导致内存泄漏。
- 创建一个可缓存的线程池:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); cachedThreadPool.execute(() -> System.out.println("Hello, world!")); cachedThreadPool.shutdown(); // 必须调用 shutdown() 才能关闭线程池。否则会导致内存泄漏。
- 创建一个单个线程的线程池:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor.execute(() -> System.out.println("Hello, world!")); singleThreadExecutor.shutdown(); // 必须调用 shutdown() 才能关闭线程池。否则会导致内存泄漏。
- 创建一个可以执行延迟任务的线程池:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2); scheduledThreadPool.scheduleAtFixedRate(() -> System.out.println("Hello, world!"), 0, 5, TimeUnit.SECONDS); scheduledThreadPool.shutdown(); // 必须调用 shutdown() 才能关闭线程池。否则会导致内存泄漏。