@Test public void testThreads() throws InterruptedException { final Logger logger = Mockito.mock(Logger.class); final int totalCount = Runtime.getRuntime().availableProcessors(); List<Future<?>> futures = new ArrayList<>(); Mockito.when(logger.isLoggable(any())).thenReturn(true); ExecutorService executor = Executors.newFixedThreadPool(totalCount); System.out.println(String.format("Will run %d threads", totalCount)); try (final Progress progress = new Progress(logger, "foo", totalCount)) { while (progress.getLoggerThread().getState() != Thread.State.WAITING) { System.out.println("Waiting for the logger thread to reach the initial wait()"); TimeUnit.MILLISECONDS.sleep(10); } for (int i = 0; i < totalCount; i++) { futures.add(executor.submit(progress::increment)); } System.out.println("Waiting for threads to finish"); futures.forEach(future -> { try { future.get(); } catch (Exception e) { Assert.fail(); } }); } executor.shutdown(); System.out.println("Verifying"); Mockito.verify(logger, atLeast(1)).log(any(), anyString(), any(Object[].class)); }
Thread getLoggerThread() { return loggerThread; }
Progress implements AutoCloseable { Thread getLoggerThread() { return loggerThread; } }
Progress implements AutoCloseable { Thread getLoggerThread() { return loggerThread; } Progress(Logger logger, String suffix, long totalCount); }
Progress implements AutoCloseable { Thread getLoggerThread() { return loggerThread; } Progress(Logger logger, String suffix, long totalCount); void increment(); @Override void close(); }
Progress implements AutoCloseable { Thread getLoggerThread() { return loggerThread; } Progress(Logger logger, String suffix, long totalCount); void increment(); @Override void close();  }