为什么ThreadPoolExecutor $ Worker扩展AbstractQueuedSynchronizer

时间:2017-02-12 15:07:48

标签: java multithreading threadpoolexecutor

我知道有关AbstractQueuedSynchronizer的一些细节。 它是一个用于创建状态依赖类或同步器的框架。 但是我没有在ThreadPoolExecutor的Worker中扩展这个类。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable

正如工人阶级的签名所见,事情可以推断出来:

  1. 提交新的Runnable / Callable任务时,会创建一个新的Worker对象。

  2. 可以将Worker的新对象视为新线程。

  3. addWorker()方法将添加新工作者(或简称为任务)并自行调用worker.start()以启动该线程。

  4. Worker类是非静态嵌套类,因此它可以访问ThreadPoolExecutor的所有变量

  5. 工程类的
  6. run()方法在内部调用runWorker(this)

    public void run(){     runWorker(本); }

  7. runWorker()执行如下的实际任务:

    void runWorker(Worker w) { try { w.lock(); w.firstTask.run() } finally { w.unlock(); } }

  8. AQS仅用于此锁定和解锁runWorker()方法。 我们不能在这里使用ReentrantLock并保持Worker类简单吗?

    同时课程提供有关此的文档,但我无法理解:

      

    此类机会性地将AbstractQueuedSynchronizer扩展为   简化获取和释放围绕每项任务的锁定   执行。这可以防止意图唤醒的中断   一个工作线程等待任务而不是中断任务   正在运行。我们实现了一个简单的非重入互斥锁   而不是使用ReentrantLock,因为我们不希望工作任务   能够在调用池控制方法时重新获取锁   比如setCorePoolSize。

    请帮忙

1 个答案:

答案 0 :(得分:3)

您的问题的答案在您发布的javadoc的引文中:

  

我们实现了一个简单的非重入互斥锁而不是   使用ReentrantLock是因为我们不希望工作任务能够   在调用池控制方法时重新获取锁   setCorePoolSize。

这是因为可能正在等待任务的线程由未被锁定表示,即tryLock为它们返回true。在这种情况下,如果ReentrantLock将在这里使用,可能会发生什么:那么可以按照一系列动作进行:

setCorePoolSize - > interruptIdleWorkers - > tryLock()(此处成功!) - > Thread.interrupt(这名工人的主持人)

会导致工作人员自行中断。