代码之家  ›  专栏  ›  技术社区  ›  user51

带线程池的Java信号量可用许可证

  •  3
  • user51  · 技术社区  · 6 年前

    https://www.baeldung.com/java-semaphore

    教程中的第一个测试(低于一个)运行良好。

    @Test
    public void givenLoginQueue_whenReachLimit_thenBlocked() {
        int slots = 10;
        ExecutorService executorService = Executors.newFixedThreadPool(slots);
        LoginQueueUsingSemaphore loginQueue = new LoginQueueUsingSemaphore(slots);
        IntStream.range(0, slots)
          .forEach(user -> executorService.execute(loginQueue::tryLogin));
        executorService.shutdown();
     
        assertEquals(0, loginQueue.availableSlots());
        assertFalse(loginQueue.tryLogin());
    }
    

    如果我评论这句话 executorService.shutdown(); 在上面的测试用例片段中,测试失败并出现以下错误。

    java.lang.AssertionError: 
    Expected :0
    Actual   :1
    <Click to see difference>
    at org.testng.AssertJUnit.fail(AssertJUnit.java:59)
    at org.testng.AssertJUnit.failNotEquals(AssertJUnit.java:364)
    at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:80)
    at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:245)
    at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:252)
    at LoginQueueSemaphoreTest.givenLoginQueue_whenReachLimit_thenBlocked(LoginQueueSemaphoreTest.java:24)
    

    测试很正常。

    我无法理解测试(可用信号量许可)如何依赖于外部线程池。另外,当我没有发布任何许可证时,1个插槽如何可用?任何简短的解释都会有帮助。提前谢谢。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Janus Varmarken    6 年前

    这是一致的行为,还是你有时会得到不同的价值观 Actual (省略 executorService.shutdown() 打电话?如果您偶尔看到其他值(比如2或3),这强烈地表明这都是由于计划/计时造成的。

    执行器服务关闭() 具有 Thread.sleep(15_000) shutdown() 调用只足以确保10个线程可以派生并执行它们的工作(调用 tryLogin() 减少 Semaphore ) 之前 assertEquals() 调用已执行。注意,根据 documentation , 关机() 启动系统的有序关闭 ExecutorService 因为它允许执行任务运行到完成,但是 电话本身 在那期间封锁。因此,执行所需的时间似乎纯属偶然 关机() 关机() 然后 awaitTermination() (或者使用 CountDownLatch 减少由工人堵塞的主螺纹),以确保 资产等价() 之后