Executors创建线程池的问题

文章目录

  • 1. Executors创建线程池存在的问题
  • 2. newFixedThreadPool
    • 2.1 测试newFixedThreadPool产生OOM情况
  • 3. newSingleThreadExecutor
  • 4. newCachedThreadPool
  • 5. newScheduledThreadPool

1. Executors创建线程池存在的问题

  1. newFixedThreadPool和 newSingleThreadExecutor:
    允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OutOfMemoryError 内存溢出。
  2. newCachedThreadPool和 newScheduledThreadPool:
    允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OutOfMemoryError 内存溢出。

2. newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • 核心线程数corePoolSize和最大线程数maximumPoolSize相等,固定长度的线程池
  • keepAliveTime是0,在线程关闭之前,创建的线程一直存在
  • LinkedBlockingQueue是一个无界阻塞队列,最大容量为Integer.MAX_VALUE。如果任务提交速度持续大余任务处理速度,会造成队列堆积大量任务,很有可能在执行拒绝策略之前就造成内存溢出
public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

2.1 测试newFixedThreadPool产生OOM情况

  1. 测试Demo
public class TestExecutors1 {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        while(true){
            executorService.execute(() -> {
                try {
                    //System.out.println(Thread.currentThread().getName());
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }


}
  1. 设置jvm参数
    设置-Xmx10m -Xms10m
    -Xmx: JVM最大堆内存
    -Xms: JVM初始堆内存大小
    Executors创建线程池的问题_第1张图片

  2. 测试结果

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
	at java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:416)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
	at com.kevin.xiancheng.TestExecutors1.main(TestExecutors1.java:15)

3. newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • 核心线程数corePoolSize和最大线程数maximumPoolSize相等都是1,即使用唯一的工作线程来执行任务
  • LinkedBlockingQueue是一个无界阻塞队列,最大容量为Integer.MAX_VALUE。如果任务提交速度持续大余任务处理速度,会造成队列堆积大量任务,很有可能在执行拒绝策略之前就造成内存溢出

4. newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • 核心线程数corePoolSize是0,最大线程数maximumPoolSize是Integer.MAX_VALUE
  • keepAliveTime是60s, 对所有空闲60s的线程进行清理
  • SynchronousQueue阻塞同步队列,该队列没有容量,是一个不会缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到 maxPoolSize,则执行拒绝策略
  • 任务处理时间长,会因为创建了太多的线程而耗尽CPU和内存资源

5. newScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

你可能感兴趣的:(java,jvm,java)