创建线程池的方式:

1、 Executors 创建:通过 Executors 工具类可以很轻松的创建我们上面java提供的几种线程池。但是实际上我们一般都不是直接使用Java提供好的线程池,另外在《阿里巴巴Java开发手册》中强制线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 构造函数 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

Executors 返回线程池对象的弊端如下:

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

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

2、 ThreadPoolExecutor的构造函数创建:

  直接调用 ThreadPoolExecutor 的构造函数来自己创建线程池。在创建的同时,给 BlockQueue 指定容量就可以了。示例如下:

private static ExecutorService executor = new ThreadPoolExecutor(13, 13,
    60L, TimeUnit.SECONDS,
    new ArrayBlockingQueue(13));

  这种情况下,一旦提交的线程数超过当前可用线程数时,就会抛出 java.util.concurrent.RejectedExecutionException ,这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。但是异常(Exception)总比发生错误(Error)要好。

3、使用开源类库

  除了自己定义 ThreadPoolExecutor 外。还有其他方法。这个时候第一时间就应该想到开源类库,如apache和guava等。”他推荐使用guava提供的 ThreadFactoryBuilder 来创建线程池。下面是参考他的代码示例:

public class ExecutorsDemo {
  private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
   .setNameFormat("demo-pool-%d").build();
  private static ExecutorService pool = new ThreadPoolExecutor(5, 200,
    0L, TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
  public static void main(String[] args) {
    for (int i = 0; i < Integer.MAX_VALUE; i++) {
      pool.execute(new SubThread());
   }
 }
}

  通过上述方式创建线程时,不仅可以避免OOM的问题,还可以自定义线程名称,更加方便的出错的时候溯源。



猜你喜欢

转载自www.cnblogs.com/guoyu1/p/12177240.html