void () { service.setBackendPoolCorePoolSize(1); ((ThreadPoolExecutor)service.backendExecutorService).prestartCoreThread(); assertEquals(1, service.getBackendPoolExecutorSize()); service.setNewThreadListener((thread, runnable) -> { Runnable firstTask = ReflectionUtil.getField(runnable.getClass(), runnable, Runnable.class, "firstTask"); String msg = "Unexpected new thread created: " + thread + "; for first task "+firstTask+"; thread dump:\n" + ThreadDumper.dumpThreadsToString(); System.err.println(msg); fail(msg); }); long submitted = System.currentTimeMillis(); AtomicBoolean agentOverloaded = new AtomicBoolean(); int delay = 1000; List<LogInfo> log = Collections.synchronizedList(new ArrayList<>()); AtomicLong f1Start = new AtomicLong(); AtomicLong f2Start = new AtomicLong(); AtomicLong f3Start = new AtomicLong(); ScheduledFuture<?> f1 = service.schedule(new Runnable() { @Override public void run() { f1Start.set(System.currentTimeMillis()); if (!log.isEmpty()) agentOverloaded.set(true); log.add(new LogInfo(1)); } @Override public String toString() { return "f1"; } }, delay, TimeUnit.MILLISECONDS); ScheduledFuture<?> f2 = service.schedule(new Runnable() { @Override public void run() { f2Start.set(System.currentTimeMillis()); if (!f1.isDone()) agentOverloaded.set(true); log.add(new LogInfo(2)); } @Override public String toString() { return "f2"; } }, delay + delay, TimeUnit.MILLISECONDS); ScheduledFuture<?> f3 = service.schedule(new Runnable() { @Override public void run() { f3Start.set(System.currentTimeMillis()); if (!f1.isDone()) agentOverloaded.set(true); if (!f2.isDone()) agentOverloaded.set(true); log.add(new LogInfo(3)); } @Override public String toString() { return "f3"; } }, delay + delay + delay, TimeUnit.MILLISECONDS); assertEquals(1, service.getBackendPoolExecutorSize()); long now = System.currentTimeMillis(); if (now > submitted + delay - 100) agentOverloaded.set(true); if (!agentOverloaded.get()) { assertFalse(f1.isDone()); assertFalse(f2.isDone()); assertFalse(f3.isDone()); } waitFor(f1::isDone); waitFor(f2::isDone); waitFor(f3::isDone); if (f2Start.get() - f1Start.get() < delay/2 || f3Start.get() - f2Start.get() < delay/2) { agentOverloaded.set(true); } if (agentOverloaded.get()) { System.err.println("This agent is seriously thrashing. I give up."); return; // no no no no. something terribly wrong is happening right now. This agent is so crazily overloaded it makes no sense to test any further. } try { assertEquals(1, service.getBackendPoolExecutorSize()); assertEquals(3, log.size()); Set<Thread> usedThreads = ContainerUtil.map2Set(log, l->l.currentThread); assertEquals(usedThreads.toString(), 1, usedThreads.size()); // must be executed in same thread } catch (AssertionError e) { System.err.println("ThreadDump:\n" + ThreadDumper.dumpThreadsToString()); System.err.println("Process List:\n" + ProcessHandle.allProcesses().map(h -> h.pid() + ": " + h.info()).collect(Collectors.joining("\n"))); throw e; } }