ThreadDeathWatcher { public static void unwatch(Thread thread, Runnable task) { if (thread == null) { throw new NullPointerException("thread"); } if (task == null) { throw new NullPointerException("task"); } schedule(thread, task, false); } private  ThreadDeathWatcher(); static void watch(Thread thread, Runnable task); static void unwatch(Thread thread, Runnable task); static boolean awaitInactivity(long timeout, TimeUnit unit);  }
@Test(timeout = 10000) public void testUnwatch() throws Exception { final AtomicBoolean run = new AtomicBoolean(); final Thread t = new Thread() { @Override public void run() { for (;;) { try { Thread.sleep(1000); } catch (InterruptedException ignore) { break; } } } }; final Runnable task = new Runnable() { @Override public void run() { run.set(true); } }; t.start(); ThreadDeathWatcher.watch(t, task); ThreadDeathWatcher.unwatch(t, task); t.interrupt(); t.join(); assertThat(ThreadDeathWatcher.awaitInactivity(Long.MAX_VALUE, TimeUnit.SECONDS), is(true)); assertThat(run.get(), is(false)); }