底层原理计划--线程与线程池
线程
线程安全的集合
Vector hashtable ===》synchronized
使用Collections包装成线程安全,本质上是将原本的集合在执行之前加上了synchronized(){}的对象锁,将对象先锁定再来运行。
===》synchronized
Synchronize lock区别 synchronized jvm 自动释放锁
Lock工具类,要unlock手动释放锁
线程池了解多少?
WHY
铺位评估批量操作、以及导入1000个店铺,如果不用线程池,就用单线程,那么执行起来是很慢的,会卡住页面,给用户的体验感不太好。
我们用线程池来提高效率,多种线程同时进行。
优点提高了效率,提高响应时间,因为线程池中的线程是可以复用的,我们只用少量的线程去执行大量的任务,这就大大减小了线程生命周期的开销。而且线程通常不是等接到任务后再临时创建,而是已经创建好时刻准备执行任务,这样就消除了线程创建所带来的延迟,提升了响应速度,增强了用户体验。
线程池使用已经创建好的线程进行循环任务处理,就避免了大量线程的频繁创建与销毁的时间成本
缺点短时间内多任务执行消耗cpu,直到执行完,开发难度维护难度加大。CPU 资源管理。
What
1、优点
降低资源消耗
提高响应速度
提高线程可关联性
2、核心参数
CorePoolSize核心线程数
核心线程数 推荐cpu核数+1
核心线程会一直存在,即使没有任务执行;当线程数小于核心线程数,即使有空闲线程,也会一直创建线程直 到达到核心线程数;
maximumPoolSize 指定线程池中最大线程数量
Workqueue工作队列
maxPoolSize最大线程数
keepAliveTime多余线程空闲时间,即多少时间多余线程的销毁
unit空闲线程存活时间单位
workQueue 任务队列,被提交但没有被执行的任务
threadFactory线程工厂,用于创建线程,一般默认的即可
handler拒绝策略,当任务太对来不及处理,如何拒绝任务
3、降低资源消耗
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动。
线程池的应用场景:有大量的数据请求,需要多执行流并发/并行处理这些任务。
线程池就是线程的池子,有很多线程,但是数量不会超过池子的限制。需要用到多执行流进行任务出路的时候,就从池子中取出一个线程去处理,线程池就类似于一个实现了消费者业务的生产者与消费者模型
How
newScheduledThreadPool
周期性线程池,创建一个定长线程池,支持定时及周期性任务执行。
创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序队列结构。
使用周期性执行任务场景
newScheduledThreadPool 创建一个线程池,安排计划执行(定期)
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
scheduledExecutorService.execute(() -> {
}
======不一样的线程池
我看到rocketmq异步发送消息的时候使用了线程池来提高效率。
this.defaultAsyncSenderExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(), 60000L, TimeUnit.MILLISECONDS, this.asyncSenderThreadPoolQueue, new ThreadFactory() {
private AtomicInteger threadIndex = new AtomicInteger(0);
另一个常用的线程池
Pulic static ExecutorService newCachedThreadPool() {
Return new ThreadPoolExectuor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
是一个可以无限扩大的线程池
比较适合处理执行时间比较小的任务
CorePoolSize为0,maximumPoolSize为无限大,线程数量可以无限大;
java线程池工作过程
1、线程池刚创建的时候,里面没有一个线程任务队列是作为参数传过来的。不过,就算队列里面有任务,线程池也不会马上执行它们。
2、当调用execute()方法添加一个任务时,线程池会做一下判断:
1 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;
2 如果正在运行线程数量大于或等于corepoolsize,那么将这个任务放入队列;(等待)
3 如果这时候队列满了,而且正在运行的线程数量小于maximumpoolsize那么还是要创建非核心线程立刻运行这个任务
4 如果队列满了,而且正在运行线程数量大于或等于maximumpoolsize,那么线程池会抛出异常rejectexecutionException
当一个线程完成任务时,它会从队列中取下一个任务来执行。
3、当一个线程无事可做,超过一定的时间(keep Alive Time)时,线程池会判断,如果当前运行的线程数大于corepoolsize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到corepoolsize的大小。
线程池的实现原理与作用:
线程池通过一个线程安全的阻塞任务队列加上一个或一个以上的线程实现,线程池中的线程可以从阻塞队列中获取任务进行任务处理,当线程都处于繁忙状态时可以将任务加入阻塞队列中,等到其它的线程空闲后进行处理
可避免大量线程频繁创建或销毁所带来的时间成本,也可避免在峰值压力下,系统资源耗尽的风险;并且可以同一对线程池中的线程进行管理,调度监控