Java Thread objects run Runnable work on separate threads. The trace records which thread produced each event, and replay uses color to show the active thread inside the same source pane.

start `start()` asks the JVM to run the task on a new thread instead of calling `run()` on the current thread.
join `join()` waits until a thread has finished before the main thread continues.

Worker Threads

limit
StartJoin.java
Replay: real traced execution (multi-file project)
public class StartJoin {
    static class Worker implements Runnable {
        private final String name;
        private final int limit;

        Worker(String name, int limit) {
            this.name = name;
            this.limit = limit;
        }

        @Override
        public void run() {
            for (int step = 1; step <= limit; step++) {
                String message = name + ":" + step;
                System.out.println(message);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int limit = 2;
        Thread alpha = new Thread(new Worker("alpha", limit));
        Thread beta = new Thread(new Worker("beta", limit));

        alpha.start();
        beta.start();
        alpha.join();
        beta.join();

        System.out.println("done");
    }
}
public class StartJoin {
    static class Worker implements Runnable {
        private final String name;
        private final int limit;

        Worker(String name, int limit) {
            this.name = name;
            this.limit = limit;
        }

        @Override
        public void run() {
            for (int step = 1; step <= limit; step++) {
                String message = name + ":" + step;
                System.out.println(message);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        int limit = 3;
        Thread alpha = new Thread(new Worker("alpha", limit));
        Thread beta = new Thread(new Worker("beta", limit));

        alpha.start();
        beta.start();
        alpha.join();
        beta.join();

        System.out.println("done");
    }
}
  1. limit ← 2

    20public static void main(String[] args) throws InterruptedException {21    int limit→ 2 = 2;  //@limit=322    Thread alpha = new Thread(new Worker("alpha", limit));23    Thread beta = new Thread(new Worker("beta", limit));
  2. this.name ← alpha, this.limit ← 2

    pass 1 of 2
    6Worker(String namealpha, int limit2) {7    this.name→ alpha = namealpha;8    this.limit→ 2 = limit2;9}
  3. alpha ← Thread[#19,Thread-0,5,main]

    21int limit = 2;  //@limit=322Thread alpha→ Thread[#19,Thread-0,5,main] = new Thread(new Worker("alpha", limit));23Thread beta = new Thread(new Worker("beta", limit));
  4. this.name ← beta, this.limit ← 2

    pass 2 of 2
    6Worker(String namebeta, int limit2) {7    this.name→ beta = namebeta;8    this.limit→ 2 = limit2;9}
  5. beta ← Thread[#20,Thread-1,5,main]

    22Thread alpha = new Thread(new Worker("alpha", limit));23Thread beta→ Thread[#20,Thread-1,5,main] = new Thread(new Worker("beta", limit));2425alpha.start();26beta.start();27alpha.join();
  6. beta.start();

    25alpha.start();26beta.start();27alpha.join();28beta.join();
  7. for (int step = 1; step <= limit; step++)

    pass 1 of 4
    12public void run() {13    for (int step1 = 1; step <= limit2; step++) {14        String message = name + ":" + step;
    All 4 passes — pass 1 is the card above
    passnamestepmessage
    11
    2beta1beta:1
    3alpha2beta:1
    4beta2beta:2
  8. alpha.join();

    26    beta.start();27    alpha.join();28    beta.join();2930    System.out.println("done");31}
    outputdone
  1. limit ← 3

    20public static void main(String[] args) throws InterruptedException {21    int limit→ 3 = 3;22    Thread alpha = new Thread(new Worker("alpha", limit));23    Thread beta = new Thread(new Worker("beta", limit));
  2. this.name ← alpha, this.limit ← 3

    pass 1 of 2
    6Worker(String namealpha, int limit3) {7    this.name→ alpha = namealpha;8    this.limit→ 3 = limit3;9}
  3. alpha ← Thread[#19,Thread-0,5,main]

    21int limit = 3;22Thread alpha→ Thread[#19,Thread-0,5,main] = new Thread(new Worker("alpha", limit));23Thread beta = new Thread(new Worker("beta", limit));
  4. this.name ← beta, this.limit ← 3

    pass 2 of 2
    6Worker(String namebeta, int limit3) {7    this.name→ beta = namebeta;8    this.limit→ 3 = limit3;9}
  5. beta ← Thread[#20,Thread-1,5,main]

    22Thread alpha = new Thread(new Worker("alpha", limit));23Thread beta→ Thread[#20,Thread-1,5,main] = new Thread(new Worker("beta", limit));2425alpha.start();26beta.start();27alpha.join();
  6. beta.start();

    25alpha.start();26beta.start();27alpha.join();
  7. alpha.join();

    26beta.start();27alpha.join();28beta.join();
  8. for (int step = 1; step <= limit; step++)

    pass 1 of 6
    12public void run() {13    for (int step1 = 1; step <= limit3; step++) {14        String message = name + ":" + step;
    All 6 passes — pass 1 is the card above
    passnamestepmessage
    11
    2alpha1alpha:1
    32alpha:1
    4alpha2alpha:2
    53
    6alpha3alpha:3
  9. beta.join();

    27    alpha.join();28    beta.join();2930    System.out.println("done");31}
    outputdone