1. 线程池的作用
创建和销毁线程都需要消耗系统资源,线程池就是为了降低系统资源消耗而存在的
线程执行完任务之后不会被销毁,而是放入线程池中,下次使用就直接在线程池中取,减少了创建和销毁线程消耗的资源
2. 使用线程池的好处
降低系统资源消耗,通过重复利用线程池中的线程来降低创建和销毁线程的消耗
提高响应速度,当任务到达时,不再需要等待创建完线程再执行
提高线程的可管理性,使用线程池可以统一对线程进行分配、调度和监控
3. 线程池的七个参数
corePoolSize:核心线程最大数量,核心线程一经创建就不会被销毁,除非线程池销毁
maximumPoolSize:线程池中最大线程数量,总线程数 = 核心线程数 + 非核心线程数
keepAliveTime:非核心线程的最大空闲时间,非核心线程在 keepAliveTime 时间后还没有执行任务,就会被销毁
unit:keepAliveTime 的时间单位,秒、分钟或者其他单位
workQueue:阻塞队列,有 ArrayBlockingQueue、LinkedBlockingQueue 等,用来存放线程任务
ThreadFactory:线程工厂,用来创建线程
RejectedExecutionHandler:拒绝策略,如果任务数量超过线程池最大负荷(),该怎么处理
AbortPolicy():丢弃当前线程任务,抛出异常
DiscardPolicy():丢弃当前线程任务,不抛异常
DiscardOldestPolicy():丢弃阻塞队列队首任务,不抛异常
CallerRunsPolicy():当前任务由调用者线程执行
4. 线程池执行任务的流程
5. Java 标准库中的线程池
Java 标准库中提供了 Executers 类来创建线程池,Executers 类创建线程池的方法有以下几种
1)newFixedThreadPool
创建一个固定线程数量的线程池,每提交一个任务就创建一个工作线程,工作线程数量达到指定的最大值,就将任务放入阻塞队列中
2)newCachedThreadPool
创建一个可缓存线程池,此类线程池中的所有线程只有 60 秒的最大空闲时间,线程空闲超过 60 秒就会被销毁,线程数量几乎没有限制
3)newScheduleThreadPool
创建一个定长的线程池,此线程池支持周期性的执行和延时执行某一个任务
使用 scheduleAtFixedRate() 或 scheduleWithFixedDelay() 即可实现周期性的任务执行
// 创建线程池 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2); // 以下两种方法结果相同,延迟五秒开始执行,每隔两秒执行一次 scheduledExecutorService.scheduleAtFixedRate(thread2, 5, 2, TimeUnit.SECONDS); scheduledExecutorService.scheduleWithFixedDelay(thread2, 5, 2, TimeUnit.SECONDS);
4)newSingleThreadExecutor
创建一个单线程化的线程池,线程池中只有唯一一个线程来执行任务,保证所有线程按照指定顺序执行,如果这个线程异常结束了,就会创建另一个线程来替代他。
6. 对比两种提交任务的方法
向线程池提交任务一般使用 execute() 和 submit()
execute() 方法用于提交不需要返回值的任务,所以无法判断任务是否被执行成功
submit() 方法用于提交需要返回值的任务,线程池会返回一个 Future 类型的对象,通过这个对象可以判断任务是否执行成功,可以通过该对象的 get() 方法获取返回值。