type
status
date
slug
summary
tags
category
icon
password

几种预定义的线程池

  • newFixedThreadPool
    • newSingleThreadExecutor
      • newCachedThreadPool
        • 这里使用的SynchronousQueue并不存储任务,因此这个线程池如果来了任务直接交给线程去执行,如果没有空闲的线程就创建,否则复用.

      submit vs execute

      有两种提交任务的方式:
      • execute(Runnable r)
        • 不返回结果
      • submit(Runnbale r)
        • 有一个Future的返回结果.
          可以看到,使用submit()提交Runnable,会使用一个RUnnableFuture包装Runnable,以返回任务结果.

      ThreadPoolExecutor中线程池的几种状态

      翻译成二进制即:
      线程池的控制状态存放在一个AtomicInteger中,一共32位:
      • 高3位表示5种运行状态,即runState
        • 为什么用3位表示?其实这里就是个简单的状态机而已,2位最多表示4种状态,3位最多表示8种状态,因此这里选择3位来表示.
      • 低29位表示有效线程数,即workerCount

      线程池的5种状态

      • Running
        • 可以接受新任务和处理队列中的任务
      • Shutdown
        • 不接受新任务,但是可以处理队列中的任务
      • Stop
        • 不接受新任务,也不处理队列中的任务,并且中断正在处理的任务
      • Tidying
        • 所有的任务已经终止了.workerCount = 0,过渡到这个状态的线程将会调用terminated()方法
      • Terminated
        • terminated()已经执行完毕
      notion image
      再来看一下这些位操作:

      Worker

      Worker本身也是Runnable,run的时候实际上运行的也是任务,而且Worker持有了Thread和Runnable,并且为线程增加了中断控制的能力.
      从代码上可以看出,Worker是复用的,不同的任务(Runnable)可能会添加到同一个Worker中,换句话说一个Worker对应一个线程,一个线程可能会运行多个任务.

      execute(Runnable r)执行过程

      基本上都是一些状态判断,然后试图添加worker.
      状态何时会启动线程,执行任务.

      总结

      看看注释说明得了,把机制弄清楚.
      代码写的真的是一言难尽.if else太多,各种稀奇古怪的判断看起来真的没什么意思.
      Golang语法快速入门Java反射
      Loading...