/** Format deadlock displaying to a user. */ public static String prettyFormat(Collection<Dependency> deadlock) { StringBuilder text = new StringBuilder(); LinkedHashSet<LocalThread> threads = new LinkedHashSet<LocalThread>(); Set<Object> seenDependers = new HashSet<>(); Object lastDependsOn = text; Object lastDepender = text; for (Dependency dep : deadlock) { Object depender = dep.getDepender(); Object dependsOn = dep.getDependsOn(); String dependerString; if (lastDependsOn.equals(depender)) { dependerString = "which"; } else if (lastDepender.equals(depender)) { dependerString = "and"; } else { dependerString = String.valueOf(depender); } lastDepender = depender; lastDependsOn = dependsOn; String also = seenDependers.contains(depender) ? " also" : ""; seenDependers.add(depender); if (depender instanceof LocalThread) { text.append(dependerString) .append(" is") .append(also) .append(" waiting on ") .append(dependsOn) .append("\n"); threads.add((LocalThread) depender); } else if (dependsOn instanceof LocalThread) { text.append(dependerString).append(" is held by thread ").append(dependsOn).append("\n"); threads.add((LocalThread) dependsOn); } else { text.append(dependerString) .append(" is") .append(also) .append(" waiting for ") .append(dependsOn) .append("\n"); } text.append("\n"); } text.append("\nStack traces for involved threads\n"); for (LocalThread threadInfo : threads) { text.append(threadInfo.getLocatility()) .append(":") .append(threadInfo.getThreadStack()) .append("\n\n"); } return text.toString(); }
public static void main(String[] args) throws InterruptedException { SynchronizedMethod sync = new SynchronizedMethod(); LocalThread a = new LocalThread(sync, "Thread A"); LocalThread b = new LocalThread(sync, "Thread B"); LocalThread c = new LocalThread(sync, "Thread C"); a.start(); b.start(); c.start(); // a.join();b.join();c.join(); }