• 线程池的使用


    1、在阿里巴巴Java开发手册中也明确指出,不允许使用Executors创建线程池。
    阿里巴巴java开发手册说明如下:
    【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

    说明:Executors返回的线程池对象的弊端如下:
    FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
    CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM

    2、固定线程池:创建固定数目线程的线程池

        public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }

    单例线程池:创建一个单线程化的Executor

        public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }

    newFixedThreadPool和newSingleThreadExecutor的阻塞队列均使用的LinkedBlockingQueue,是一个用链表实现的阻塞队列,不设置容量的话,默认最大长度为Integer.MAX_VALUE,这样就不断的向队列中加入任务的,创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致OOM。

    3、

    public class ThreadPoolExecutorUtils {
    
        private static int CORE_POOL_SIZE = 10;
        private static int MAX_POOL_SIZE = 20;
        private static long KEEP_ALIVE_TIME = 30;
        private static int QUEUE_SIZE = 200;
        private static String THREAD_POOL_NAME = "thread-pool";
        private static volatile ExecutorService pool = null;
    
        private ThreadPoolExecutorUtils(){
    
        }
        public static ExecutorService getPool() {
            // 使用双重校验锁保证只有一个pool实例
            if (pool == null) {
                synchronized (ThreadPoolExecutorUtils.class) {
                    if (pool == null) {
                        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(THREAD_POOL_NAME + "-%d").build();
                        pool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
                                new LinkedBlockingQueue<>(QUEUE_SIZE), namedThreadFactory,
                                new ThreadPoolExecutor.AbortPolicy());
                    }
                }
            }
            return pool;
        }
    }        

    总结引用:https://mp.weixin.qq.com/s/kefLFjLTOZuwmklrMPAOLA

    N核服务器,通过执行业务的单线程分析出本地计算时间为x,等待时间为y,则工作线程数(线程池线程数)设置为 N*(x+y)/x,能让CPU的利用率最大化。

    一般来说,非CPU密集型的业务(加解密、压缩解压缩、搜索排序等业务是CPU密集型的业务),瓶颈都在后端数据库访问或者RPC调用,本地CPU计算的时间很少,所以设置几十或者几百个工作线程是能够提升吞吐量的。

  • 相关阅读:
    JaveScript简单数据类型(JS知识点归纳二)
    JaveScript变量的简介及其变量的简单使用(JS知识点归纳一)
    JaveScript用二分法与普通遍历(冒泡)
    include、include_once、require、require_once其区别
    POST和GET有什么区别?
    前端向后台发送请求有几种方式?
    jQuery的$.ajax方法响应数据类型有哪几种?本质上原生ajax响应数据格式有哪几种,分别对应哪个属性?
    java根据汉字生成首字母大写
    springboot+使用切面AOP动态获取自定义注解
    JavaScript基础05——严格模式
  • 原文地址:https://www.cnblogs.com/tilamisu007/p/12056294.html
Copyright © 2020-2023  润新知