• 线程池的3个方法,7大参数,4种拒绝策略


    线程池的3个方法,7大参数,4种拒绝策略

    一、3个创建线程池的方法

    1. Executors.newSingleThreadExecutor(); // 单个线程的线程池
    2. Executors.newFixedThreadPool(5); // 固定大小的线程池
    3. Executors.newCachedThreadPool(); // 可伸缩的线程池,遇强则强,遇弱则弱
    

    阿里开发手册中:

    线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下:

    1) FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

    2) CachedThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

    以下为三种创建方法的函数的源码:

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    以下就是 ThreadPoolExecutor 函数,有7大参数,下节详细阐述。

    二、线程池的7大参数

    (1) corePoolSize:核心线程数(当等待队列不满的时候,只会调用核心线程)

    (2) maximumPoolSize:最大线程数(当等待队列满了的时候,会激活更多的线程)

    (3) keepAliveTime:新激活的线程在没有任务的情况下的存活时间

    (4) TimeUnit:keepAliveTime 的单位

    (5) BlockingQueue:阻塞队列,当核心线程满了,新的请求会在队列中等待

    (6) ThreadFactory:创建线程的工厂,使用默认的 Executors.defaultThreadFactory() 即可

    (7) RejectedExecutionHandler:拒绝策略,当超出线程池的最大承载时的拒绝策略(有4种拒绝策略)

    现在我们再来看看阿里开发手册中的两句话:

    1) FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

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

    newSingleThreadExecutor 中的传入的阻塞队列参数为 new LinkedBlockingQueue<Runnable>() ,而 LinkedBlockingQueue 的默认构造函数的队列长度为 Integer.MAX_VALUE 约等于21亿,所以可能会堆积大量的请求,从而导致 OOM。FixedThreadPool同理。

    2) CachedThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    newCachedThreadPool 中的传入的最大线程数参数为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

    那么最大线程数应该如何定义呢?分以下两种情况:

    1. CPU 密集型:几个核心就定义为几,可以保证 CPU 的效率最高,例如一个4核的 CPU,则可以令 maximumPoolSize = 4,其中可以使用 Runtime.getRuntime().availableProcessors() 获取 CPU 的核数。
    2. IO 密集型:程序中有很多大型任务,IO 十分占用资源!此时要判断程序中十分消耗 IO 的线程数,只要大于该数即可,一般可以设置为两倍。

    三、4种拒绝策略

    (1) ThreadPoolExecutor.AbortPolicy():当达到线程池的最大承载时,还有请求,则不处理,并且抛出异常。

    (2) ThreadPoolExecutor.CallerRunsPolicy(): 当达到线程池的最大承载时,还有请求,那条线程请求那条线程去处理,一般为 main 线程。

    (3) ThreadPoolExecutor.DiscardPolicy(): 当达到线程池的最大承载时,还有请求,则丢掉任务,并且不抛出异常。

    (4) ThreadPoolExecutor.DiscardOldestPolicy(): 当达到线程池的最大承载时,还有请求,则尝试去和最老的线程竞争, 并且不抛出异常。

  • 相关阅读:
    Linux重定向命令
    ls命令
    Linux常用命令_(进程管理)
    Linux常用命令_(文件操作)
    Linux常用命令_(文件查看)
    Linux常用命令_(文件搜索)
    Oracle表空间管理
    如何测试数据库表空间不足场景
    find命令
    各种比例尺标准分幅图经差、纬差表
  • 原文地址:https://www.cnblogs.com/xiekun96/p/14290196.html
Copyright © 2020-2023  润新知