线程池参数动态化Demo


关于如何实现线程池参数动态化

自定义线程池类

public class MyThreadPool{
    /**
     * 最大可用的CPU核数
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    /**
     * 核心线程数量大小,如果是CPU 密集型任务(N+1),如果是I/O 密集型任务(2N),N为CPU核心数
     */
    private static final int corePoolSize = CPU_COUNT * 2;

    /**
     * 线程池最大容纳线程数
     */
    private static final int maximumPoolSize = CPU_COUNT * 4;

    enum SingletonEnum {
        //单例
        INSTANCE;

        private ThreadPoolExecutor executorService;
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("thread-pool-%d")
                .setDaemon(true).build();

        private SingletonEnum() {
            executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 10L,
                    TimeUnit.MILLISECONDS, new ResizableCapacityLinkedBlockingQueue<>(100), threadFactory,new MyRejectedExecutionHandler());
        }

        public ThreadPoolExecutor getInstance() {
            return executorService;
        }
    }

    public static ThreadPoolExecutor getInstance() {
        return MyThreadPool.SingletonEnum.INSTANCE.getInstance();
    }
}

自定义拒绝策略和自定义队列

//自定义拒绝策略
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        throw new RejectedExecutionException("Task " + r.toString() +
                " rejected from " +
                executor.toString());
    }
}

//自定义队列
//复制一份LinkedBlockingQueue的代码块,命名为ResizableCapacityLinkedBlockingQueue,并将 private final int capacity;这行代码改成:
private volatile int capacity;

public int getCapacity() {
    return capacity;
}

public void setCapacity(int capacity) {
    this.capacity = capacity;
}

Controller层

public class MyCustomizedController {

    ThreadPoolExecutor cachedThreadPool = MyThreadPool.getInstance();

    @ApiOperation(value = "修改核心线程数", notes = "")
    @GetMapping("/corePoolSize")
    public ResponseVO setCorePoolSize(@RequestParam("corePoolSize") Integer corePoolSize) {
        if(cachedThreadPool.getMaximumPoolSize()<corePoolSize){
            return ResponseVO.success("设置失败,目标核心线程数大于前最大线程数,请同时设置两者的值或重新设置值");
        }
        cachedThreadPool.setCorePoolSize(corePoolSize);
        return ResponseVO.success("设置成功");
    }

    @ApiOperation(value = "修改最大线程数", notes = "")
    @GetMapping("/maximumPoolSize")
    public ResponseVO setMaximumPoolSize(@RequestParam("maximumPoolSize") Integer maximumPoolSize) {
        cachedThreadPool.setMaximumPoolSize(maximumPoolSize);
        return ResponseVO.success("设置成功");
    }

    @ApiOperation(value = "修改核心线程数和最大线程数", notes = "")
    @GetMapping("/coreAndMax")
    public ResponseVO setcoreAndMax(@RequestParam("corePoolSize") Integer corePoolSize,@RequestParam("maximumPoolSize") Integer maximumPoolSize) {
        if(corePoolSize>maximumPoolSize){
            return ResponseVO.success("设置失败,核心线程数不应大于最大线程数");
        }
        cachedThreadPool.setCorePoolSize(corePoolSize);
        cachedThreadPool.setMaximumPoolSize(maximumPoolSize);
        return ResponseVO.success("设置成功");
    }

    @ApiOperation(value = "修改队列长度", notes = "")
    @GetMapping("/capacity")
    public ResponseVO setCapacity(@RequestParam("capacity") Integer capacity) {
        ResizableCapacityLinkedBlockingQueue queue = (ResizableCapacityLinkedBlockingQueue) cachedThreadPool.getQueue();
        queue.setCapacity(capacity);
        return ResponseVO.success("设置成功");
    }

    @ApiOperation(value = "线程池情况",notes = "")
    @GetMapping("/poolStatus")
    public ResponseVO getPoolStatus(){
        log.info("查看当前线程池状态");
        String str = getStatus();
        return ResponseVO.success("线程池情况:"+str);
    }

    private String getStatus() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ResizableCapacityLinkedBlockingQueue queue = (ResizableCapacityLinkedBlockingQueue) cachedThreadPool.getQueue();
        String str =sdf.format(new Date())+Thread.currentThread().getName() + "-" +
                "核心线程数:" + cachedThreadPool.getCorePoolSize() +
                ",活动线程数" + cachedThreadPool.getActiveCount() +
                ",最大线程数" + cachedThreadPool.getMaximumPoolSize() +
                ",线程池活跃度" + divide(cachedThreadPool.getActiveCount(), cachedThreadPool.getMaximumPoolSize()) +
                ",任务完成数" + cachedThreadPool.getCompletedTaskCount() +
                ",队列大小" + (queue.size() + queue.remainingCapacity()) +
                ",当前排队线程数" + queue.size() +
                ",队列剩余大小" + queue.remainingCapacity() +
                ",队列使用度" + divide(queue.size(), queue.size() + queue.remainingCapacity());
        log.info(str);
        return str;
    }

    /**
     * 保留两位小数
     * @param num1
     * @param num2
     * @return
     */
    private static String divide(int num1, int num2) {
        return String.format("%1.2f%%", Double.parseDouble(num1 + "") / Double.parseDouble(num2 + "") * 100);
    }
}

配合CountDownLatch并发编程工具类使用

//n个任务
ThreadPoolExecutor cachedThreadPool = MyThreadPool.getInstance();
CountDownLatch countDownLatch = new CountDownLatch(n);
cachedThreadPool.execute(
                ()->{
                    //业务代码****
                    countDownLatch.countDown();
                });
try {
            countDownLatch.await();
        } catch (Exception e) {
            log.info("任务中断");
        }

参考学习链接

Java线程池实现原理及其在美团业务中的实践
如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值