Java线程池中的线程发生OOM会如何?

95 篇文章 3 订阅
60 篇文章 2 订阅

环境:JDK1.8


线程池中如果发生OOM后会如何?

线程池ThreadPoolExecutor当有线程发生了OOM,线程池会停止工作吗?

public static void main(String[] args) {
  ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2)) ;
  pool.execute(() -> {
    int i = 0 ;
    for (;;) {
      System.out.println(Thread.currentThread().getName() + ", i = " + (i++) + "," + pool) ;
		  try {
        TimeUnit.MILLISECONDS.sleep(50) ;
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  });
  pool.execute(() -> {
    int j = 0 ;
    for (;;) {
      System.out.println(Thread.currentThread().getName() + ", j = " + (j++) + "," + pool) ;
      try {
        TimeUnit.MILLISECONDS.sleep(50) ;
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  });
  pool.execute(() -> {
    int k = 0 ;
    List<byte[]> datas = new ArrayList<>() ;
    for (;;) {
      System.out.println(Thread.currentThread().getName() + ", k = " + (k++) + "," + pool) ;
      byte[] buf = new byte[1024 * 100] ;
      datas.add(buf) ;
      try {
        TimeUnit.MILLISECONDS.sleep(20) ;
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  });
}

调整JVM运行内存

-Xms10m -Xmx10m

执行结果:

Java线程池中的线程发生OOM会如何?

 

一开始3个线程交替执行,当其中一个线程发生OOM后,线程池中除了发生OOM的线程池不再继续工作外,其它的线程都继续工作。

自定义线程异常处理

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS,
  new ArrayBlockingQueue<Runnable>(2), new ThreadFactory() {
    private final ThreadGroup group = new ThreadGroup("Pack-Group");
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix = "pool-custom-thread-";

   @Override
  public Thread newThread(Runnable r) {
    Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
    t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
      @Override
      public void uncaughtException(Thread t, Throwable e) {
        System.out.println("自定义线程异常处理:" + t.getName());
        e.printStackTrace();
     }});
    return t;
  }
});

线程池的拒绝策略

代码:

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.AbortPolicy()) ;
  for (int i = 0; i < 6; i++) {
    pool.execute(() -> {
      System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
      try {
        TimeUnit.SECONDS.sleep(2) ;
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    });
  }
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;

1、AbortPolicy策略

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.AbortPolicy()) ;

Java线程池中的线程发生OOM会如何?

 

当任务数 > 线程数 + 队列大小。超过的任务直接拒绝并且抛出异常。程序不会继续往下执行。

2、CallerRunsPolicy策略

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.CallerRunsPolicy()) ;

Java线程池中的线程发生OOM会如何?

 

超过的任务会由调用者线程(执行execute方法所在的线程)执行任务。

3、DiscardOldestPolicy策略

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardOldestPolicy()) ;
for (int i = 0; i < 5; i++) {
  pool.execute(() -> {
    System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
    try {
      TimeUnit.SECONDS.sleep(2) ;
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  });
}
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;
pool.execute(() -> {
  System.out.println(Thread.currentThread().getName() + ", 我是新入任务") ;
});

执行结果:

Java线程池中的线程发生OOM会如何?

 

该策略会把任务队列中的列头删除,然后将自己放入队列(列尾)

Java线程池中的线程发生OOM会如何?

 

4、DiscardPolicy策略

ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), new ThreadPoolExecutor.DiscardPolicy()) ;
for (int i = 0; i < 7; i++) {
  pool.execute(() -> {
    System.out.println(Thread.currentThread().getName() + ", 进入执行") ;
    try {
      TimeUnit.SECONDS.sleep(2) ;
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  });
}
System.out.println("ActiveCount: " + pool.getActiveCount()) ;
System.out.println("PoolSize: " + pool.getPoolSize()) ;
System.out.println("TaskCount: " + pool.getTaskCount()) ;
TimeUnit.SECONDS.sleep(5) ;
pool.execute(() -> {
  System.out.println(Thread.currentThread().getName() + ", 新任务执行") ;
});

执行结果:

Java线程池中的线程发生OOM会如何?

 

该策略什么也不做,线程池能够正常继续执行下去。

Java线程池中的线程发生OOM会如何?

 

自定义线程池

自定义线程池监控线程执行耗时时间

public class CustomThreadPool extends ThreadPoolExecutor {
  public CustomThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
    BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
  }
  @Override
  protected void beforeExecute(Thread t, Runnable r) {
    super.beforeExecute(t, r);
    if (r instanceof Task) {
      ((Task) r).setStart(System.currentTimeMillis()) ;
      System.out.println(t.getName() + ", 开始执行") ;
    }
  }
  @Override
  protected void afterExecute(Runnable r, Throwable t) {
    super.afterExecute(r, t);
    if (r instanceof Task) {
      ((Task) r).times();
    }
  }
  public void execute(Task command) {
    super.execute(command);
  }
  public static class Task implements Runnable {
    private long start ;
    private Callback callback ;
    public Task(Callback callback) {
      this.callback = callback ;
    }
    @Override
    public void run() {
      if (this.callback != null) {
        this.callback.callback();
      }
    }
    public void times() {
      System.out.println(Thread.currentThread().getName() + " 执行耗时:" + (System.currentTimeMillis() - start) + "ms") ;
    }
    public void setStart(long start) {
      this.start = start;
    }
		
  }
  public static interface Callback {
    void callback() ;
  }
}

重写beforeExecute,afterExecute父类的这两个方法,线程执行前和执行后。

CustomThreadPool pool = new CustomThreadPool(3, 3, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2)) ;
pool.execute(new Task(() -> {
  try {
    TimeUnit.SECONDS.sleep(1) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
})) ;
pool.execute(new Task(() -> {
  try {
    TimeUnit.SECONDS.sleep(3) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
})) ;
pool.execute(new Task(() -> {
  try {
    TimeUnit.SECONDS.sleep(2) ;
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
})) ;

执行结果:

Java线程池中的线程发生OOM会如何?

给个关注谢谢

Java线程池中的线程发生OOM会如何?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值