线程池好像每一次参加面试的时候,都会问道,自己之前确实没有使用过什么,今天大致结合看网上博客,发现了一篇写的很好的博客,略作修改,写下
原博客地址强烈推荐这个作者写的博客,思路很清晰!!!
什么是线程池
线程池当中缓存了一定数量的线程,线程池实现了对于线程的管理和复用(最重要的就是实现对线程的复用,避免频繁创建线程和销毁线程带来的开销),当然管理的可以实现线程执行的统一分配以及调优
必须知道的线程池核心参数
- corePoolsize
核心线程数 : 默认的情况下会一直存活下去(空闲的时候也存活) - maximumPoolSize
线程池所能容纳的最大线程数 : 当活动线程数到达该数值之后,后续的新任务将会阻塞 - keepAliveTime
非核心线程 闲置超时时长 : 超过该时长,非核心线程会被回收(当执行alllowThreadTimeout为true的时候,keepAliveTime同时用于核心线程) - unit 指定keepAliveTiem参数的时间单位 : TimeUnit.MILLSECONDS(毫秒),TimeUnit.SECONDS(秒),TimeUnit.MINUTES(分)等等
- workQeue
任务队列 : 通过线程池的execute()方法提交Runnable对象,存储在该参数中 - threadFactory
线程工厂 : 为线程创建新线程
这6个参数的配置决定了线程池的作用,在创建线程池类的时候传入
ThreadPoolExecutor 是线程类的实现类,我们可以通过它实现自定义线程池
1
2
Executor executor=new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue)
}
内部逻辑原理
ThreadPool使用流程
- 创建线程池
创建时,通过配置线程池的参数,从而实现自己所需的线程池Executor threadPool = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory );
-
向线程池提交任务:execute()
// 说明:传入 Runnable对象 threadPool.execute(new Runnable() { @Override public void run() { ... // 线程执行任务 } });
- 关闭线程池shutdown()
threadPool.shutdown();
关闭线程的原理
a. 遍历线程池中的所有工作线程
b. 逐个调用线程的interrupt()中断线程(注:无法响应中断的任务可能永远无法终止) 也可调用shutdownNow()关闭线程:threadPool.shutdownNow() 二者区别:
shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程
shutdownNow:设置线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()
Java内部实现好了的4类功能线程池
根据参数的不同配置,Java最常见的线程池有4类,其实这四个线程池都是通过ThreadPoolExecutor
调整6个参数而创建而成
- 定长线程池(FixedThreadPool)
- 定时线程池(ScheduledThreadPool)
- 可缓存线程池(CachedThreadPool)
- 单线程化线程池(SingleThreadExecutor)
定长线程池(FixedThreadPool)
- 特点:只有核心线程 & 不会被回收、线程数量固定、任务队列无大小限制(超出的线程任务会在队列中等待)
- 应用场景:控制线程最大并发数
- 具体使用:通过 Executors.newFixedThreadPool() 创建
示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
ExecutorService fixThreadPool=Executors.newFixedThreadPool(3);//最大并发量为3 for(int i=0;i<6;i++){ final int index=i; fixThreadPool.execute(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { System.out.println("当前线程"+Thread.currentThread()+" 执行任务"+index); Thread.sleep(2000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } //这个程序最多只有三个线程在执行
定时线程池(ScheduledThreadPool )
- 特点:核心线程数量固定、非核心线程数量无限制(闲置时马上回收)
- 应用场景:执行定时 / 周期性 任务
- 使用:通过Executors.newScheduledThreadPool()创建
示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
ScheduledExecutorService scheduleThreadpool=Executors.newScheduledThreadPool(3); Runnable task=new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { System.out.println("当前线程"+Thread.currentThread()); Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; scheduleThreadpool.schedule(task, 1,TimeUnit.SECONDS);//延迟一秒执行任务 scheduleThreadpool.scheduleAtFixedRate(task, 10, 2000, TimeUnit.MILLISECONDS);//延迟 10ms 周期的执行
可缓存线程池(CachedThreadPool)
- 特点:只有非核心线程、线程数量不固定(可无限大)、灵活回收空闲线程(具备超时机制,全部回收时几乎不占系统资源)、新建线程(无线程可用时)源码中显示是通过60s回收线程
- 任何线程任务到来都会立刻执行,不需要等待
-
应用场景:执行大量、耗时少的线程任务 使用:通过Executors.newCachedThreadPool()创建
示例: ```
ExecutorService cachedThreadPool=Executors.newCachedThreadPool(); Runnable task=new Runnable() {1 2 3 4 5 6 7 8 9 10 11 12 13 14
@Override public void run() { // TODO Auto-generated method stub try { System.out.println("当前线程"+Thread.currentThread()); Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; for(int i=0;i<10;i++)//直接创建10个线程执行 cachedThreadPool.execute(task);```
单线程化线程池(SingleThreadExecutor)
- 特点:只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题)
- 应用场景:不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等
- 使用:通过Executors.newSingleThreadExecutor()创建
示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
ExecutorService singleThradPool=Executors.newSingleThreadExecutor(); Runnable task=new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { System.out.println("当前线程"+Thread.currentThread()); Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; for(int i=0;i<10;i++) singleThradPool.execute(task);//只有一个线程执行,执行完之后才执行下一个任务