并发--线程池

线程池

类之间的关系

Executor和ExecutorService

  • 1.Executor只有execute方法。
  • 2.ExecutorService在继承了Executor之后提供了其他的诸如shutdown等管理线程池的方法

ThreadPoolExecutor是ExecutorService的具体实现类

Worker是Runnable类型,是线程具体执行任务

  • 1.我们启动的线程都会被包装成该类,然后类里面已经定义了执行前后逻辑,以及去任务队列获取线程,或者超时注销的逻辑。

关键方法

execute

  • 1.首先判断当前工作线程数量是否小于核心线程数,小于则直接开启新的线程执行,如果开启失败大概率是因为线程池关闭。则执行reject
  • 2.如果大于了核心线程数,确保线程池还在运行的状态,则将任务放入任务队列。放入队列之后再次检测线程池状态是否处于运行状态
    如果不是则移除任务并执行reject,如果上述条件不成立则查看工作线程是否为0,如果是则开启额外线程去消费任务队列里面的任务。
  • 3.走到第三步代表我们任务队列已经满了或者线程池不再运行状态此时我们尝试开启一个线程去执行,如果开启失败则执行 reject。

addWorker

  • 0.自旋的方式执行1,2,3.
  • 1.首先检测线程池是否已经关闭了。
  • 2.如果是STOP,TIDYING,TERMINATED状态的话,则会返回false,如果现在状态是SHUTDOWN,但是firstTask不为空或者workQueue为空的话,那么直接返回false。
  • 3.内部小自旋增加woker线程的数量标志。成功了进行下一步,不成功执行1,2。
  • 4.生成一个新的worker,然后采用mainLock锁住,然后启动worker。
  • 5.在执行beforeExecute之前会有如下的判断逻辑:1.如果线程池已停止且线程未中断,条件成立,中断线程 2.如果线程池未停止,线程为中断状态,将线程状态重置,并重新进行1的判断3.如果线程池未停止,线程不为中断状态,条件不成立
  • 6.只要上述情况发送了我们就重置中断状态,保证中断标志可以传播
  • 7.我们在getTask获取不到任务会执行processWorkerExit,其判断如果是异常退出还是正常退出,并且如果线程池如果未关闭还会生成新的线程执

getTask

  • 1.其是woker线程获取task的主要逻辑
  • 2.线程池已经stop或者shutdown且任务队列为空则将该线程关闭。
  • 3.判断是否需要超时获取队列,只要allowCoreThreadTimeOut或者woker数量大于核心线程数。
  • 4.如果worker大于maximumPoolSize或者需要超时或者上一次轮训是超时,与此同时还需要满足wc大于或者任务队列是空的
  • 5.从队列获取任务,可以根据我们的timed来选择是否阻塞还是非阻塞获取。
  • 6.如果没获取到任务正在执行了则代表超时,如果被中断了设置timeOut=false

processWorkerExit

  • 1.该方法主要是在woker线程结束之后需要调用的方法。
  • 2.如果completedAbruptly则该worker会被注销(其实该线程肯定要被注销,关键在于我们是否需要重启线程)
  • 3.mainLock锁住,然后将该线程执行的任务添加到completedTaskCount
  • 4.然后调用tryTerminate
  • 5.如果线程池还未stop(只是shutdown或者running)则会调用addWorker(并不会开启成功 因为会检测任务队列是否还有任务,没有则不增加)
  • 6.如果completedAbruptly是false,代表应该是因为没有任务才退出的则这个时候检测是否存在任务,如果存在则min应该设置为1,如果running的大于min则不需要重启线程
  • 7.对于FIX这种 getTask会一直阻塞。

tryTerminate

  • 1.把线程池状态转换为terminated,但是只有在线程池为shutdown且线程池和任务队列都是空;或者线程池状态是stop和线程池为空。

shutdownNow和shutdown

  • 0.shutdown的方法如下:
  • 1.先尝试将线程池状态设置为shutdown
  • 2.对于所有空闲线程调用interupt(防止他们阻塞在等待获取任务,他们醒来发现线程池shutdown了 则会退出)
  • 3.onShutdown 这是一个钩子方法
  • 4.然后执行tryTerminate
  • 5.shutdownNow的逻辑是先修改状态为STOP,然后中断所有线程(也会防止在正在运行中阻塞的线程),将所有未执行的任务返回。

Callable到runnbale的转换以及Future的原理

  • 1.首先把callable转化为FutureTask,该类是Runnable, Future的子类。
  • 2.futureTask就是调用runnable的run方法,在run方法里面执行callabe的call方法,并把结果设置outcome
  • 3.future方法在调用get的时候会检测是否已经可以获取get了。中间检测不可获取的时候会沉睡。

invokeAll和invokeAny

  • 1.invokeAll是执行所有任务,invokeAny只执行任务中的一个。

worker

关键方法就是执行runWorker

  • 1.该方法是while方法,每次查看firstTask是否存在,是的话就执行,否则从任务队列获取。
  • 2.每次执行前查看线程池状态是否还在运行状态。
  • 3.每次执行前后都可以执行beforeExecute和afterExecute ,整个执行过程被worker的锁住了

worker还是继承AQS独占锁,直接CAS设置state,没有等待队列。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容