/** 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();
  }