Java线程池总结

Java线程池总结
一、线程池的概念及优势

​ 线程在使用时需要创建,使用完需要销毁,而创建、销毁线程会消耗系统资源(内存、CPU),重复操作会导致大量资源浪费。从而就需要使用池化技术----线程池,减少线程对象的创建、回收次数,提高服务效率。

线程池具有以下几点优势:

1.降低资源销毁:

通过重复利用已经创建的线程,降低线程创建和销毁造成的消耗

2.提高响应速度

当任务到达时,任务可以不需要等到线程创建就能立即执行

3.防止服务器过载

不会形成内存溢出,或者CPU耗尽

4.提高线程的可管理性

线程是稀缺资源,如果无限制地创建,不仅会消耗资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控

二、线程池的参数及选择策略

线程池的真正实现类是 ThreadPoolExecutor,来自于抽象类 AbtractExecutorService,而 AbtractExecutorService实现了ExecutorService接口,ExecutorService接口继承于Executor接口

1.构造方法:
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(),handler);
}
2.其中的几个参数:

corePoolSize:线程池中的核心线程数量,在没有用的时候,也不会被回收

maximumPoolSize:线程池中可以容纳的最大线程的数量

keepAliveTime:线程池中除了核心线程之外的其他的最长可以保留的时间,因为在线程池中,除了核心线程即使在无任务的情况下也不能被清除,其余的都是有存活时间的,意思就是非核心线程可以保留的最长的空闲时间

util:计算时间的一个单位

workQueue:等待队列,任务可以储存在任务队列中等待被执行,执行的是FIFIO原则(先进先出)

handler:拒绝策略

其中有4种拒绝策略:

a.AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满,默认该方式。

b.CallerRunsPolicy:直接调用execute来执行当前任务。

c.DiscardPolicy:丢弃任务,但是不抛出异常。

d.DiscardOldestPolicy:抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。先从任务队列中弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列。

3.参数选择策略:

线程池核心线程数的设置?

cpu密集型:cpu个数+1

io密集型:2*cpu个数+1

1.高并发、任务执行时间短的业务怎样使用线程池?

高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换

2.并发不高、任务执行时间长的业务怎样使用线程池?

假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以适当加大线程池中的线程数目,让CPU处理更多的业务。

假如是业务时间长集中在计算操作上,也就是计算密集型任务,线程池中的线程数设置得少一些,减少线程上下文的切换

三、常见的4种线程池

newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

  • 特点:无核心线程,非核心线程数量无限,执行完闲置 60s 后回收,任务队列为不存储元素的阻塞队列。
  • 应用场景:执行大量、耗时少的任务。

创建方式:

ExecutorService pool=Executors.newCachedThreadPool();
pool.execute(()->{
    
});

newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  • 特点:只有核心线程,线程数量固定,执行完立即回收,任务队列为链表结构的有界队列。
  • 应用场景:控制线程最大并发数。

创建方式:

ExecutorService pool=Executors.newFixedThreadPool(2);//固定两个线程
pool.execute(()->{
    
});

newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。

  • 特点:核心线程数量固定,非核心线程数量无限,执行完闲置 10ms 后回收,任务队列为延时阻塞队列。
  • 应用场景:执行定时或周期性的任务。

创建方式:

ExecutorService pool=Executors.newScheduledThreadPool(5);//5个线程
pool.scheduleAtFixedRate(()->{

},0,2,TimeUnit.SECONDS);//每两秒执行一个线程

newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

创建方式:

ExecutorService pool=Executors.newSingleThreadExecutor();
pool.execute(()->{
    
});
  • 特点:只有 1 个核心线程,无非核心线程,执行完立即回收,任务队列为链表结构的有界队列。
  • 应用场景:不适合并发但可能引起 IO 阻塞性及影响 UI 线程响应的操作,如数据库操作、文件操作等。
收藏 (0)
评论列表
正在载入评论列表...
我是有底线的