线程池的学习
Posted SSimeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池的学习相关的知识,希望对你有一定的参考价值。
线程池的学习
1. 什么是线程池?
线程池:一种线程使用模式。 线程池就是首先创建一些线程,它们的集合称为线程池。
线程过多会带来调度开销,进而影响缓存局部性和整体性能,而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动一条线程来执行这个任务,执行结束以后,该线程并不会死亡,而是再次返回线程池中成为空闲状态,等待执行下一个任务。使用线程池避免了在处理短时间任务时创建与销毁线程的代价。
2. 为什么要使用线程池?
线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。
好处:
- 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行
- 降低资源销毁:通过重复利用已经创建的线程,降低线程创建和销毁造成的消耗
- 防止服务器过载:形成内存溢出,或者CPU耗尽。
- 提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。
3. 常用的线程池有哪些?
- (newCachedThreadPool)可缓存的线程池:该线程池中没有核心线程,非核心线程的数量为Integer.max_value。当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++)
try
//sleep可明显看到使用的是线程池里面以前的线程,没有创建新的线程
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
cachedThreadPool.execute(new Runnable()
public void run()
//打印正在执行的缓存线程信息
System.out.println(Thread.currentThread().getName()+"正在被执行");
);
- (newScheduledThreadPool)周期性执行任务的线程池:按照某种特定的计划执行线程中的任务,有适用于执行周期性的任务。
//创建一个定长线程池,支持定时及周期性任务执行——延迟执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//延迟1秒执行
scheduledThreadPool.schedule(new Runnable()
public void run()
System.out.println("延迟1秒执行");
, 1, TimeUnit.SECONDS);
- (newSingleThreadPool)单线程池:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++)
final int index = i;
singleThreadExecutor.execute(new Runnable()
public void run()
try
//结果依次输出,相当于顺序执行各个任务
System.out.println(Thread.currentThread().getName()+"正在被执行,打印的值是:"+index);
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
);
- (newFixedThreadPool)定长的线程池:有核心线程,核心线程数量即为最大的线程数量,没有非核心线程
//创建一个可重用固定个数的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++)
fixedThreadPool.execute(new Runnable()
public void run()
try
//打印正在执行的缓存线程信息
System.out.println(Thread.currentThread().getName()+"正在被执行");
Thread.sleep(2000);
catch (InterruptedException e)
e.printStackTrace();
);
4 线程池的配置参数。
5 线程池工作原理。
有新的任务时,首先判断核心线程是否处于空闲状态,如果是空闲状态,核线程就先执行任务,如果核心线程已满,则判断任务队列是否已满,如果没满就将任务保存在任务队列中,等待执行,如果满了,再判断有没有超出线程池最大可容纳的线程数,如果没有超出这个数量,就开创非核心线程执行任务,如果超出了,就调用handler实现拒绝策略。
6 线程池的handler拒绝策略
有四种:
- 1.AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
- 2.DisCardPolicy:不执行新任务,也不抛出异常
- 3.DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
- 4.CallerRunsPolicy:直接调用execute来执行当前任务
以上是关于线程池的学习的主要内容,如果未能解决你的问题,请参考以下文章