ThreadDeadlockDetector { public Set<String> getDeadlockedThreads() { final long[] ids = threads.findDeadlockedThreads(); if (ids != null) { final Set<String> deadlocks = new HashSet<String>(); for (ThreadInfo info : threads.getThreadInfo(ids, MAX_STACK_TRACE_DEPTH)) { final StringBuilder stackTrace = new StringBuilder(); for (StackTraceElement element : info.getStackTrace()) { stackTrace.append("\t at ") .append(element.toString()) .append(String.format("%n")); } deadlocks.add( String.format("%s locked on %s (owned by %s):%n%s", info.getThreadName(), info.getLockName(), info.getLockOwnerName(), stackTrace.toString() ) ); } return Collections.unmodifiableSet(deadlocks); } return Collections.emptySet(); } ThreadDeadlockDetector();  ThreadDeadlockDetector(ThreadMXBean threads); Set<String> getDeadlockedThreads(); int getDeadlockedThreadCount();  }
@Test public void returnsAnEmptySetIfNoThreadsAreDeadlocked() throws Exception { when(threads.findDeadlockedThreads()).thenReturn(null); assertThat(detector.getDeadlockedThreads()) .isEmpty(); }
@Test public void returnsASetOfThreadsIfAnyAreDeadlocked() throws Exception { final ThreadInfo thread1 = mock(ThreadInfo.class); when(thread1.getThreadName()).thenReturn("thread1"); when(thread1.getLockName()).thenReturn("lock2"); when(thread1.getLockOwnerName()).thenReturn("thread2"); when(thread1.getStackTrace()).thenReturn(new StackTraceElement[]{ new StackTraceElement("Blah", "bloo", "Blah.java", 150), new StackTraceElement("Blah", "blee", "Blah.java", 100) }); final ThreadInfo thread2 = mock(ThreadInfo.class); when(thread2.getThreadName()).thenReturn("thread2"); when(thread2.getLockName()).thenReturn("lock1"); when(thread2.getLockOwnerName()).thenReturn("thread1"); when(thread2.getStackTrace()).thenReturn(new StackTraceElement[]{ new StackTraceElement("Blah", "blee", "Blah.java", 100), new StackTraceElement("Blah", "bloo", "Blah.java", 150) }); final long[] ids = { 1, 2 }; when(threads.findDeadlockedThreads()).thenReturn(ids); when(threads.getThreadInfo(eq(ids), anyInt())) .thenReturn(new ThreadInfo[]{ thread1, thread2 }); assertThat(detector.getDeadlockedThreads()) .containsOnly(String.format(Locale.US, "thread1 locked on lock2 (owned by thread2):%n" + "\t at Blah.bloo(Blah.java:150)%n" + "\t at Blah.blee(Blah.java:100)%n"), String.format(Locale.US, "thread2 locked on lock1 (owned by thread1):%n" + "\t at Blah.blee(Blah.java:100)%n" + "\t at Blah.bloo(Blah.java:150)%n")); }
@Test public void autoDiscoversTheThreadMXBean() throws Exception { assertThat(new ThreadDeadlockDetector().getDeadlockedThreads()) .isNotNull(); }