说明
- Java线程池是一种池化技术,它将多个线程放在一个线程池中,以便在需要时可以重复使用这些线程,从而节省了线程创建和销毁的开销。
原理
- 创建线程池:线程池被创建时,它会创建一组线程并将它们放入一个池中,这个池就是线程池。
- 提交任务:当需要执行任务时,可以将任务提交给线程池,线程池会将任务放入任务队列中。
- 从任务队列中获取任务:线程池中的线程会从任务队列中获取任务并执行它们。
- 执行任务:线程池中的线程会执行任务并将结果返回给调用者。
- 重复利用线程:当线程执行完任务后,它会返回线程池并等待下一个任务。这样,线程可以重复使用,从而避免了线程创建和销毁的开销。
- 关闭线程池:当线程池不再需要时,可以关闭线程池,并释放线程池中的所有线程。
工作流程
- 线程在有任务的时候会创建核心的线程数corePoolSize
- 当线程满了(有任务但是线程被使用完)不会立即扩容,而是放到阻塞队列中,当阻塞队列满了之后才会继续创建线程。
- 如果队列满了,线程数达到最大线程数则会执行拒绝策略。
- 当线程数大于核心线程数事,超过KeepAliveTime(闲置时间),线程会被回收,最终会保持corePoolSize个线程。
四大策略
- AbortPolicy(被拒绝了抛出异常)
- CallerRunsPolicy(使用调用者所在线程执行,就是哪里来的回哪里去)
- DiscardOldestPolicy(尝试去竞争第一个,失败了也不抛异常)
- DiscardPolicy(默默丢弃、不抛异常)
七大核心参数
- corePoolSize: 线程池核心线程个数
- workQueue:用于保存等待执行任务的阻塞队列
- maximunPoolSize: 线程池最大线程数量
- ThreadFactory: 创建线程的工厂
- RejectedExecutionHandler: 队列满,并且线程达到最大线程数量的时候,对新任务的处理策略
- keeyAliveTime: 空闲线程存活时间
- TimeUnit: 存活时间单位
实现
- Java线程池可以使用Java Executor框架来实现,该框架提供了各种类型的线程池,如固定大小的线程池、可缓存线程池、单线程线程池等。这些线程池可以根据应用程序的需求进行配置,以提高应用程序的性能。
- newSingleThreadExecutor():池里只有一条线程,如果线程因为异常而停止,会自动新建一个线程补充
- newFixedThreadPool():创建一个核心线程数跟最大线程数相同的线程池,线程池数量大小不变,如果有任务放入队列,等待空闲线程。
- newCachedThreadPool():线程池是创建一个核心线程数为0,最大线程为Inter.MAX_VALUE的线程池,线程池数量不确定,有空闲线程则优先使用,没用则创建新的线程处理任务,处理完放入线程池。
- newScheduledThreadPool():创建一个没有最大线程数限制的可以定时执行线程池,还有创建一个只有单个线程的可以定时执行线程池(Executors.newSingleThreadScheduledExecutor())
手动创建好处
手动创建线程池可以根据实际需求对线程池的大小、线程的创建、销毁、调度等进行灵活的控制和调整,从而更好地满足系统的需求,可以提高系统的稳定性、性能、安全性和可维护性,提供更多的控制和调整方式,是进行多线程编程的常用方式