java线程池学习

1.传统方式创建线程池的弊端

1.传统方式通过 ExecutorService executorService = Executors.newCachedThreadPool() 创建线程池  虽然简化了开发人员的创建流程 但是由于这种方式隐藏了线程池内部的原理 在线上可能存在很大的风险 故需要手动创建线程池(默认的方式 线程池采用队列没有指定大小 采用无界队列Integer.MAX 在高并发环境下 容易导致服务器资源枯竭)

2.推荐创建方式

 

  /**
     * 方式1  阿里推荐方式
     */
    private ThreadFactory threadFactory=new ThreadFactoryBuilder()
            .setNameFormat("longyi-")
            .build();
    ThreadPoolExecutor executor=new ThreadPoolExecutor(20,30,0, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100),threadFactory,new ThreadPoolExecutor.AbortPolicy());

    @Bean("asyncExecute")
    public Executor asyncExecute() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(5);
        // 最大线程数
        executor.setMaxPoolSize(10);
        // 配置缓存队列数
        executor.setQueueCapacity(20);
        // 配置最大空闲时间
        executor.setKeepAliveSeconds(60);
        // 前缀
        executor.setThreadNamePrefix("stock-thread-");
        // 线程池对拒绝任务的处理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);

        return executor;
    }

3. 线程池拒绝策略

(1)ThreadPoolExecutor.AbortPolicy 丢弃任务,并抛出 RejectedExecutionException 异常。

(2)ThreadPoolExecutor.CallerRunsPolicy:该任务被线程池拒绝,由调用 execute方法的线程执行该任务。

(3)ThreadPoolExecutor.DiscardOldestPolicy : 抛弃队列最前面的任务,然后重新尝试执行任务。

(4)ThreadPoolExecutor.DiscardPolicy,丢弃任务,不过也不抛出异常。

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略。

4.线程队列

从有界无界上分

常见的有界队列为

ArrayBlockingQueue 基于数组实现的阻塞队列

LinkedBlockingQueue 其实也是有界队列,但是不设置大小时就是无界的。

ArrayBlockingQueue 与 LinkedBlockingQueue 对比一哈

ArrayBlockingQueue 实现简单,表现稳定,添加和删除使用同一个锁,通常性能不如后者

LinkedBlockingQueue 添加和删除两把锁是分开的,所以竞争会小一些

SynchronousQueue 比较奇葩,内部容量为零,适用于元素数量少的场景,尤其特别适合做交换数据用,内部使用 队列来实现公平性的调度,使用栈来实现非公平的调度,在Java6时替换了原来的锁逻辑,使用CAS代替了

上面三个队列他们也是存在共性的

put take 操作都是阻塞的

offer poll 操作不是阻塞的,offer 队列满了会返回false不会阻塞,poll 队列为空时会返回null不会阻塞

补充一点,并不是在所有场景下,非阻塞都是好的,阻塞代表着不占用CPU,在有些场景也是需要阻塞的,put take 存在必有其存在的必然性

常见的无界队列

ConcurrentLinkedQueue 无锁队列,底层使用CAS操作,通常具有较高吞吐量,但是具有读性能的不确定性,弱一致性——不存在如ArrayList等集合类的并发修改异常,通俗的说就是遍历时修改不会抛异常

PriorityBlockingQueue 具有优先级的阻塞队列

DelayedQueue 延时队列,使用场景

缓存:清掉缓存中超时的缓存数据

5.基本原理图

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值