AffinityGroupThreadFactory implements ThreadFactory { @Override public synchronized Thread newThread(@Nullable final Runnable r) { final int num = id.getAndIncrement(); final String threadName = String.format("%s-%s", threadNamePrefix, num); LOGGER.info("Create new thread called '{}'.", threadName); final Thread t = new Thread(new Runnable() { @Override public void run() { addThread(); verifyNotNull(r).run(); removeThread(); } }, threadName); t.setUncaughtExceptionHandler(exceptionHandler); t.setDaemon(createDaemonThreads); return t; } AffinityGroupThreadFactory(String name,
      UncaughtExceptionHandler uncaughtExceptionHandler);  AffinityGroupThreadFactory(String name,
      UncaughtExceptionHandler uncaughtExceptionHandler, boolean daemon); @Override synchronized Thread newThread(@Nullable final Runnable r); @Override String toString();  }
@Test public void test() throws InterruptedException { if (!Affinity.isJNAAvailable() || Runtime.getRuntime().availableProcessors() <= 2) { return; } final ExcepHandler handler = new ExcepHandler(); assertThat(getReservations()).isEmpty(); final AffinityGroupThreadFactory fac = new AffinityGroupThreadFactory(NAME, handler); assertThat(getReservations()).isEmpty(); final Thread t0 = fac.newThread(new SleeperRunnable()); final Thread t1 = fac.newThread(new SleeperRunnable()); final Thread t2 = fac.newThread(new SleeperRunnable()); assertThat(t0.getName()).isEqualTo(NAME + "-0"); assertThat(t1.getName()).isEqualTo(NAME + "-1"); assertThat(t2.getName()).isEqualTo(NAME + "-2"); t0.start(); Thread.sleep(200L); assertThat(getReservations()).hasSize(1); final ThreadInfo ti2 = getReservations().get(0).getThreadInfo().get(); assertThat(ti2.getCpuId()).isGreaterThan(0); assertThat(ti2.isAlive()).isTrue(); assertThat(ti2.getName()).isEqualTo(NAME); t1.start(); Thread.sleep(200L); assertThat(getReservations()).hasSize(1); final ThreadInfo ti3 = getReservations().get(0).getThreadInfo().get(); assertThat(ti3.getCpuId()).isGreaterThan(0); assertThat(ti3.isAlive()).isTrue(); assertThat(ti3.getName()).isEqualTo(NAME); final Thread rogueThread1 = createThread("Rogue thread"); rogueThread1.start(); Thread.sleep(200L); assertThat(getReservations()).hasSize(2); final ThreadInfo ti3a = getReservationByName("Rogue thread"); assertThat(ti3a.isAlive()).isTrue(); assertThat(ti3a.getCpuId()).isGreaterThan(0); assertThat(ti3a.getCpuId()).isNotSameAs(ti3.getCpuId()); t0.interrupt(); Thread.sleep(200L); assertThat(getReservations()).hasSize(2); final ThreadInfo ti4 = getReservationByName(NAME); assertThat(ti4.getCpuId()).isEqualTo(ti3.getCpuId()); assertThat(ti4.getCpuId()).isGreaterThan(0); assertThat(ti4.isAlive()).isTrue(); rogueThread1.interrupt(); Thread.sleep(200L); assertThat(rogueThread1.isAlive()).isFalse(); assertThat(getReservations()).hasSize(1); getReservationByName(NAME); t1.interrupt(); Thread.sleep(25L); assertThat(getReservations()).isEmpty(); final Thread rogueThread2 = createThread("Rogue thread 2"); rogueThread2.start(); t2.start(); Thread.sleep(25L); assertThat(getReservations()).hasSize(2); final ThreadInfo ti5 = getReservationByName(NAME); assertThat(ti5.getCpuId()).isGreaterThan(0); assertThat(ti5.isAlive()).isTrue(); assertThat(ti5.getName()).isEqualTo(NAME); final ThreadInfo ti6 = getReservationByName("Rogue thread 2"); assertThat(ti6.getCpuId()).isEqualTo(ti3.getCpuId()); assertThat(ti6.isAlive()).isTrue(); assertThat(ti6.getName()).isEqualTo("Rogue thread 2"); t2.interrupt(); rogueThread2.interrupt(); }