线程池用过吗?生产上如何设置合理参数

线程池的拒绝策略

一、为什么要采用拒绝策略

等待队列已经排满了,再也塞不下新任务
线程池的中的max线程数 也达到了,无法继续为新任务服务
这个时候,我们需要拒绝策略机制 去 合理的处理这个问题

二、Jdk内置的几种拒绝策略

1、AbortPolicy (默认) :直接抛出RejectedExecutionException异常阻止系统正常运行

2、CallerRunsPolicy :调用者运行,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退给调用者,从而降低新任务的流量

3、DiscardOldestPolicy : 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

4、DiscardPolicy :直接丢弃任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种方案

这几种策略都是实现了RejectedExecutionHandler 接口

jdk提供的单一的、固定的、可变的三种创建线程池的方法,用哪个多

这个一个坑来的 ,阿里巴巴开发手册就明确规定 关于线程池不能使用 Executors 去创建。要手写

线程池用过吗?生产上如何设置合理参数_第1张图片

如何合理的配置线程池参数

一、CPU密集型

这种就是该任务需要大量的计算,而没有阻塞,cpu一直全速进行
cpu密集任务 只有在多核cpu上才可能得到加速(通过多线程)

公式 = cpu 核数 + 1 (尽量满足一核一个,减少切换)

IO密集型

两种选择方式
一种是考虑 他不是一直在执行任务,所以需要尽可能多的线程,如CPU核数 * 2

一种考虑到IO密集型,大部分线程都阻塞,因此需要多配置线程数 :
参考公式 : cpu核数 /(1 - 阻塞系数) 阻塞系数:0.8 ~ 0.9
比如8核cpu :8 / (1 - 0.9)=80个线程数

下面手写一个线程池demo

package com.demo.ThreadPool;

import java.util.concurrent.*;
import java.util.function.Supplier;

/**
 * 手写线程池的案例
 */
public class ThreadPoolExecutorUtils {
     
    /**
     * 采用单例模式
     */
    private static volatile ThreadPoolExecutorUtils instance;

    private static ThreadPoolExecutor threadPoolExecutor;


    /**
     * 构造器私有化
     */
    private ThreadPoolExecutorUtils () {
     
        //初始化线程池
        setThreadPoolExecutor(() -> {
     
            //如果是cpu 密集型 则传入 cpu核数 + 1
            //如果是io密集型 则传入 cpu核数 * 2  或者 cpu核数 / (1 - 0.9) 阻塞系数是0.8 ~ 0.9
            return Runtime.getRuntime().availableProcessors() + 1;
        });
    }

    /**
     * 创建单例
     */
    public static ThreadPoolExecutorUtils getInstance () {
     
        /**
         * 采用双重检查 提高效率 保证懒加载
         */
        if (instance == null) {
     
            synchronized (ThreadPoolExecutorUtils.class) {
     
                if (instance != null) {
     
                    instance = new ThreadPoolExecutorUtils();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化线程池
     */
    private static void setThreadPoolExecutor (Supplier< Integer > supplier) {
     

        threadPoolExecutor = new ThreadPoolExecutor(
                supplier.get(),
                supplier.get(),
                1L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100),//这里要根据网站访问量来调整
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy()

        );
    }
}


你可能感兴趣的:(面试题集合)