MENU

Java线程池

Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。
201926

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

相关参数

  • corePoolSize:线程池中线程的数量
  • maximumPoolSize:线程池中最大的线程数量
  • keepAliveTime:当线程池数量超过corePoolSize值时,多余的空闲线程等待新任务的最长时间
  • unit:keepAliveTime单位
  • workQueue:执行前用于保持任务的队列
  • threadFactory:线程工厂,用于创建线程
  • handler:拒绝策略

handler(拒绝策略)分类

作用:当线程池中线程已经耗尽且等待队列也已经排满,则对于新任务采取合理的拒绝处理。

  • AbortPolicy:该策略直接抛出异常(默认拒绝策略)
  • CallerRunsPolicy:该策略线程直接调用运行该任务的execute本身。
  • DiscardOldestPolicy:该策略直接丢弃最老的一个请求任务。
  • DiscardPolicy:该策略直接丢弃无法处理的任务,不做任何处理(与AbortPolicy类似,但不抛出异常)

线程池类型

  • newCachedThreadPool:创建一个可缓存的线程池。线程池大小依赖于JVM能够创建的最大线程大小。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有60秒钟未被使用的线程。
  • newSingleThreadExecutor:创建一个单线程的线程池,当该唯一线程因为异常退出会重新创建一个新线程。能够按照任务提交的顺序有序执行。
  • newFixedThreadPool:创建一个固定大小的线程池,并以无界队列方式来运行这些线程。
  • newScheduledThreadPool:创建一个大小无限,它可安排在给定延迟后运行命令或者定期地执行

可能在日常开发中我们习惯性的创建一个线程池方法:

ExecutorService pool = Executors.newCachedThreadPool();

但是在阿里巴巴开发规范守约中提示:
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式, 这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明: Executors各个方法的弊端:

  • newFixedThreadPooL和newSingleThreadExecutor:主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
  • newCachedThreadPooL和newScheduledThreadPool:主要问题是线程数最大数是Integer.MAX_VALUE, 可能会创建数量非常多的线程,甚至OOM。

任务队列

  • SynchronousQueue:不存储数据、可用于传递数据。每一个put操作必须等待一个take操作,否则不能继续添加元素。
  • LinkedBlockingQueue:基于链表的阻塞队列。能够高效的处理并发数据,对于生产者和消费者端分别采用独立的锁来控制数据同步,以此提高整个队列的并发性能。
  • ArrayBlockingQueue:用数组实现的有界阻塞队列。默认情况下不保证访问者公平的访问队列。
标签: Java
返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码