1.首先我们来看一下为什么使用线程池,使用线程池能给我们的系统带来什么样子的好处?
①:降低资源消耗:减少了创建线程和销毁线程的次数,每个工作线程都可以重复被利用,可执行多个任务
②:提高响应速度:当任务到达时,可以不用等待线程的创建就能立即执行。
③:提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性。使用线程池可以统一的进行分配、调优和监控。
2.如何创建线程池?
根据阿里编码规范手册,我们不能使用Executors工具类来帮我们创建线程池,而是需要我们根据线程核心类【ThreadPoolExecutor】来手写线程池。那么就涉及到线程池的7大参数,下面我们来看一下线程池的7个核心参数。
3.线程池的7大核心参数
corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTime:多余的空闲线程的存活时间
unit:keepAliveTime的单位
workQueue:任务队列,被提交但尚未执行的任务
threadFactory:线程池中工作线程的创建工厂。用于创建线程一般使用默认的即可。
handler:拒绝策略。表示当任务队列已满并且工作线程的数量大于线程池中的最大线程数【maximumPoolSize】的时候,启用的饱和拒绝策略。
4.线程池的工作原理?
通过上面的讲解,我们已经了解了创建线程池的核心参数的意义。那么下面我们来看一下线程池的工作原理,深入了解各个参数的具体含义。
线程池工作流程如下:
1.首先用户提交任务到线程池,判断当前工作的线程数量有没有大于核心线程数【corePoolSize】
→如果小于核心线程数,则创建线程并执行任务。
→如果大于核心线程数,则判断队列是否已满
→如果任务队列没有满,则把任务缓存到任务队列中【workQueue】
→如果任务队列已满,则判断当前工作线程数量是否大于最大线程数量【maximumPoolSize】
→如果没有大于最大线程数量,则创建线程并执行任务
→如果大于最大线程数量,则启用线程池的拒绝策略【handler】
为了让大家更加直观的感受,我特意画了一张工作流程图
5.线程池的拒绝策略
AbortPolicy:【默认】直接抛出RejectedExecutionException异常,阻止系统正常运行
DiscardPolicy:直接丢弃任务,不与任何处理,也不抛出异常。如果允许任务丢失,这是一种好的方案。
DiscardOldestPolicy:抛弃队列中等待最久的任务,然后把当前任务添加都队列中,尝试再次提交当前任务
CallerRunsPolicy:"呼叫着运行"一种调试机制。该策略既不会抛弃任务,也不会抛出异常。而是将某些任务回退给调用者,从而降低新任务的流量。
6.小tip
身为IT工作者,我们要有属于自己独特的方式去查看电脑的线程数。使用以下代码即可查看电脑的线程数!
System.out.println("当前电脑线程数量是:"+Runtime.getRuntime().availableProcessors());