当前位置:   article > 正文

8、ThreadPoolExecutor源码_workercountof(recheck) == 0

workercountof(recheck) == 0

一、线程池有哪些类

1、可缓存线程池(NewCachedThreadPool)

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行
很多短期异步任务的程序而言,这些线程池通常可提高程序性能。


2、 指定工作线程的线程池(NewFixedThreadPool)

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。


3、定时的线程池(newScheduledThreadPool)

创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

4、ThreadPoolExecutor

ThreadPoolExecutor与前几个线程池对比要更灵活

二、ThreadPoolExecutor解决什么问题

创建一个新的线程可以通过继承Thread类或者实现Runnable接口来实现,这两种方式创建的线程在运行结束后会被虚拟机销毁,进行垃圾回收,如果线程数量过多,频繁的创建和销毁线程会浪费资源,降低效率。而线程池的引入就很好解决了上述问题,线程池可以更好的创建、维护、管理线程的生命周期,做到复用,提高资源的使用效率,也避免了开发人员滥用new关键字创建线程的不规范行为。


1、ThreadPoolExecutor数据结构

ThreadPoolExecutor数据结构有 HashSetBlockingQueue、Worker、AbstractQueuedSynchronizer构成。

2、ThreadPoolExecutor执行流程

1、任务添加 - 当线程池任务数小于核心线程数时,Worker 是继承Runnable的包装类,每一个任务都使用Worker包装起来,然后将包装对象存入HashSet中,直接唤醒其线程执行。 

2、任务添加 - 当线程池任务数大于核心线程数时,执行方法直接放入BlockingQueue队列中,排队执行。如果队列满了执行队列拒绝策略。

3、线程回收- 当执行线程大于核心线程 或者 线程池关闭 或者 核心线程keepAliveTimeOut超时时候触发interruptIdleWorkers方法。 注意点interruptIdleWorkers回收原则是线程是否被发出中断请求,如果被发出中断请求执行回收。

三、ThreadPoolExecutor类重点方法列举

属性名称解释功能描述
keepAliveTime线程空闲时间一个线程处在空闲状态的时间超过了该属性值,就会因为超时而退出。举个例子,如果线程池的核心大小corePoolSize=5,而当前大小poolSize =8,那么超出核心大小的线程,会按照keepAliveTime的值判断是否会超时退出。如果线程池的核心大小corePoolSize=5,而当前大小poolSize =5,那么线程池中所有线程都是核心线程,这个时候线程是否会退出,取决于allowCoreThreadTimeOut
allowCoreThreadTimeOut核心线程超时关闭该属性用来控制是否允许核心线程超时退出。默认值为:false。如果线程池的大小已经达到了corePoolSize,不管有没有任务需要执行,线程池都会保证这些核心线程处于存活状态。该属性只是用来控制核心线程的
poolSize线程池中当前线程的数量线程池中当前线程的数量,当该值为0的时候,意味着没有任何线程
corePoolSize核心线程数线程池的基本大小,即在没有任务需要执行的时候线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程。这里需要注意的是:在刚刚创建ThreadPoolExecutor的时候,线程并不会立即启动,而是要等到有任务提交时才会启动,除非调用了prestartCoreThread/prestartAllCoreThreads事先启动核心线程。再考虑到keepAliveTime和allowCoreThreadTimeOut超时参数的影响,所以没有任务需要执行的时候,线程池的大小不一定是corePoolSize
maximumPoolSize线程池中允许的最大线程数线程池中允许的最大线程数,线程池中的当前线程数目不会超过该值。如果队列中任务已满,并且当前线程个数小于maximumPoolSize,那么会创建新的线程来执行任务。这里值得一提的是largestPoolSize,该变量记录了线程池在整个生命周期中曾经出现的最大线程个数。为什么说是曾经呢?因为线程池创建之后,可以调用setMaximumPoolSize()改变运行的最大线程的数目
queueCapacity任务队列容量(阻塞队列当核心线程数达到最大时,新任务会放在队列中排队等待执行
rejectedExecutionHandler任务拒绝处理器 * 两种情况会拒绝处理任务:
       - 当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务
       - 当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务
        * 线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常
        * ThreadPoolExecutor类有几个内部实现类来处理这类情况:
            - AbortPolicy 丢弃任务,抛运行时异常
            - CallerRunsPolicy 执行任务
            - DiscardPolicy 忽视,什么都不会发生
            - DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务
        * 实现RejectedExecutionHandler接口,可自定义处理器

四、线程池源码解读

1、任务添加

1、当前线程数小于核心线程数,addWoker直接添加入Hashset中,直接唤醒addWorker线程执行。

  1. public void execute(Runnable command) {
  2. if (command == null)
  3. throw new NullPointerException();
  4. int c = ctl.get();
  5. //线程小于核心线程数,addWorker添加Hashset直接唤醒线程执行
  6. if (workerCountOf(c) < corePoolSize) {
  7. if (addWorker(command, true))
  8. return;
  9. c = ctl.get();
  10. }
  11. //任务添加到队列
  12. if (isRunning(c) && workQueue.offer(command)) {
  13. int recheck = ctl.get();
  14. if (! isRunning(recheck) && remove(command))
  15. reject(command);
  16. else if (workerCountOf(recheck) == 0)
  17. addWorker(null, false);
  18. }
  19. //任务添加队列失败执行拒绝策略
  20. else if (!addWorker(command, false))
  21. reject(command);
  22. }

2、队列任务执行

线程池队列线程执行情况

  1. final void runWorker(Worker w) {
  2. Thread wt = Thread.currentThread();
  3. Runnable task = w.firstTask;
  4. w.firstTask = null;
  5. w.unlock(); // allow interrupts
  6. boolean completedAbruptly = true;
  7. try {
  8. while (task != null || (task = getTask()) != null) {
  9. w.lock();
  10. // 如果线程池停止执行线程回收
  11. // 如果当前线程被中断
  12. if ((runStateAtLeast(ctl.get(), STOP) ||
  13. (Thread.interrupted() &&
  14. runStateAtLeast(ctl.get(), STOP))) &&
  15. !wt.isInterrupted())
  16. wt.interrupt();
  17. try {
  18. beforeExecute(wt, task);
  19. Throwable thrown = null;
  20. try {
  21. task.run();
  22. } catch (RuntimeException x) {
  23. thrown = x; throw x;
  24. } catch (Error x) {
  25. thrown = x; throw x;
  26. } catch (Throwable x) {
  27. thrown = x; throw new Error(x);
  28. } finally {
  29. afterExecute(task, thrown);
  30. }
  31. } finally {
  32. task = null;
  33. w.completedTasks++;
  34. w.unlock();
  35. }
  36. }
  37. completedAbruptly = false;
  38. } finally {
  39. processWorkerExit(w, completedAbruptly);
  40. }
  41. }

3、线程池线程回收

线程回收方法是线程安全的,如果线程被中断执行回收。

  1. //线程池线程回收
  2. private void interruptIdleWorkers(boolean onlyOne) {
  3. final ReentrantLock mainLock = this.mainLock;
  4. mainLock.lock();
  5. try {
  6. for (Worker w : workers) {
  7. Thread t = w.thread;
  8. if (!t.isInterrupted() && w.tryLock()) {
  9. try {
  10. t.interrupt();
  11. } catch (SecurityException ignore) {
  12. } finally {
  13. w.unlock();
  14. }
  15. }
  16. if (onlyOne)
  17. break;
  18. }
  19. } finally {
  20. mainLock.unlock();
  21. }
  22. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Guff_9hys/article/detail/812564
推荐阅读
相关标签
  

闽ICP备14008679号