JUC_线程池

概述

        线程过多会带来调度开销,进而影响缓存局部性和整体性能;而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务,避免了在处理短时间任务时创建与销毁线程的代价;线程池不仅能够保证内核的充分利用,还能防止过分调度

设置线程池的最大线程数可参照:JUC_CPU密集型与I/O密集型_Mudrock__的博客-CSDN博客

创建线程池

方式一:通过Executors工具类

通过Executors可创建四种线程池,分别可创建固定大小的线程池,大小为一的线程池,大小可变的线程池,支持定时性、周期性任务的线程池

        Executors.newFixedThreadPool(5);    //固定大小的线程池
        Executors.newSingleThreadExecutor();//大小为一的线程池
        Executors.newCachedThreadPool();    //大小可变的线程池
        Executors.newScheduledThreadPool(5);//支持定时性、周期性任务的线程池(参数为corePoolSize)

不建议通过Executor创建线程池,原因如下:

使用Executors的弊端:
FixedThreadPool和SingleThreadPool:
    允许请求的队列长度为Integer.MAX_VALUE 可能会堆积大量的请求 导致OOM
CachedThreadPool和ScheduledThreadPool:
    允许创建的线程数量为Integer.MAX_VALUE 可能会创建大量的线程 导致OOM

方式二:通过ThreadPoolExecutor类

public ThreadPoolExecutor(int corePoolSize,     //核心线程数(或者称最小线程数 线程池存在期间会持续开启的线程的数量)当线程数小于核心线程数时 即使此时存在闲置核心线程 线程池也会优先创建新线程处理新任务
                      int maximumPoolSize,      //最大线程数 当请求的线程数大于corePoolSize+workQueue时 开启额外线程(但总线程数不超过maximumPoolSize)
                      long keepAliveTime,       //线程最长闲置时间(闲置时间超过阈值则关闭线程 直至线程数等于corePoolSize为止)
                      TimeUnit unit,            //最长闲置时间的单位
                      BlockingQueue<Runnable> workQueue,    //线程阻塞队列 当请求的线程数大于corePoolSize时 线程进入BlockingQueue阻塞队列
                      ThreadFactory threadFactory,          //线程工厂 用于创建一组任务相同的线程(一般不做改变)
                      RejectedExecutionHandler handler) {   //拒绝策略 当workQueue队列达到上限后 可执行拒绝策略(四种拒绝策略 一般使用默认策略AbortPolicy)

四种拒绝策略
AbortPolicy 抛出异常(默认拒绝策略)
CallerRunsPolicy 让线程的调用者线程代为执行
DiscardPolicy 不抛出异常(同时也不处理任务)
DiscardOldestPolicy 尝试和运行最久的线程竞争(不一定竞争得过 竞争不过就不被处理 也不抛出异常)

示例代码

public class TestThreadPoolExecutor {
    public static void main(String[] args) {
        ExecutorService threadPool =  new ThreadPoolExecutor(
                5,
                20,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
                );

        try {
            for (int i = 0; i < 500; i++) {
                threadPool.execute(()->{
                    System.out.println(Thread.currentThread().getName());
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            threadPool.shutdown();
        }
    }
}

运行效果

可以看到,允许的最大线程数为20,此时若再有线程申请执行,且申请完成后程池中的20条线程均未执行完成,线程数将会超过20,此时会抛出异常,此即为AbortPolicy拒绝策略

若将AbortPolicy拒绝策略改成CallerRunsPolicy拒绝策略,当线程数超过允许的最大线程数时,超过部分的线程的任务将会由线程的调用者线程代为执行

可以看到main线程代为执行了超过部分的线程的任务(线程池中的线程是由main线程调用的,所以代为执行者为main线程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值