JDK自带的构建线程池的方式之newSingleThreadExecutor

235 阅读2分钟

newSingleThreadExecutor从名称上就可以知道这个是一个单例的线程池。在这个线程池中只有一个线程来处理任务。 就可以使用在业务涉及到顺序消费的时候。

newSingleThreadExecutor的代码展示

  • 可以从这个在Executors中的静态方法newSingleThreadExecutor可以发现,该线程池的实现的最内部也是通过ThreadPoolExecutor来进行创建,并把线程数设置为1。
  • 在使用的时候就会出现第一个任务过来进线程池中执行,后续任务则会在LinkedBlockingQueue无界队列中等待上一个任务线程执行完任务之后才能执行。由于只有一个线程在线程池中和队列中任务投递过来的顺序就是线程处理的顺序,从而实现了顺序执行的任务逻辑。

在这里插入图片描述

newSingleThreadExecutor中FinalizableDelegatedExecutorService方法分析

  • 首先这个是在创建好了ThreadPoolExecutor之后外面在包装一层,有点类似于设计模式中的装饰者模式,对类的功能进行了增强。
  • 查看内部的代码发现并没有什么特别之处。super是调用父类的方法,和正常执行创建ThreadPoolExecutor没有什么区别。
  • 重写了finalize方法。该方法是GC在回收对象时要执行的方法。方法体中的含义显而易见就是在对象回收之前让当前线程shutdown,停止掉当前线程。但是由于finalize在执行的时候是守护线程,会随着主线程的执行结束就结束了,所以可能并不能每一次都理想的执行掉shutdown方法来关闭线程。因此就会造成JVM中存在一定概率的线程堆积问题。
  • 所以我们在日常的使用时一定要在业务逻辑执行完成之后手动shutdown

在这里插入图片描述

newSingleThreadExecutor代码效果演示

  • 不难发现每一次获取的线程名称都是一样的。

在这里插入图片描述

  • 发现在执行完成线程池任务之后要是没有手动shutdown,会出现JVM堆积大量线程的问题。

在这里插入图片描述

  • 执行完shutdown就可以解决线程堆积的问题

在这里插入图片描述

有一点需要注意的是,要是创建的线程是作为全局变量进行使用,在局部变量中执行完成业务逻辑关闭掉线程池之后会影响后续的逻辑执行。 在这里插入图片描述