Displaying threads alternatively in JAVA

I see two solutions:

  1. Busy Wait

Each thread wait before printing. And release when the condition is true. I used AtomicInteger for indexToPrint to make this value sync for every thread.

This solution works with n number of threads.

import java.util.concurrent.atomic.AtomicInteger;

class Task extends Thread {
    
    final static private AtomicInteger indexToPrint = new AtomicInteger(0);

    static private int threadNumber = 0;

    final private int index;

    /**
     *
     */
    public Task() {
        index = threadNumber++;
    }


    private int nextIndex() {
        return (index + 1) % threadNumber;
    }

    @Override
    public void run() {

        try {    

            for(int i = 0; i<10; i++){

                double dure = Math.random()*200 ;
                sleep((long) dure);

                while (indexToPrint.get() != index) {
                    sleep((long) 10);
                }
                indexToPrint.set(nextIndex());
                
                System.out.println(Thread.currentThread().getName());
                
            }
        } catch (Exception e) {}
    }
}
  1. wait and notify

A bit more complex to understand, but no useless CPU use. Let's explain how the synchronized block synchronized (indexToPrint) {...} works. The block is synchronized monitoring the static object indexToPrint. This object is static (common to every thread), so only one thread can simultaneously enter this block.

When one thread enter the block, if its index is different from indexToPrint then the thread is stopped with wait() making it possible for another thread to enter the block. Else, the thread name is printed, the indexToPrint is updated to next thread index and all thread are waken up with notifyAll(). Finally, it left the block.

All threads waiting are now awake, and the actual thread left the block. So one thread can try again to print.

It's important to understand that when a thread is put to wait and then notify, it runs exactly where it was stopped. Here, a thread can be stopped at two positions: before the synchronized block and at the wait call.

The while is very essential here. All thread are waking up with notifyAll(), so after waking up they should test themselves again.

You can find a good documentation here.

The code is based on the previous one. With same use of indexToPrint.

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

class Task extends Thread {

    static private final AtomicInteger indexToPrint = new AtomicInteger(0);

    static private int threadNumber = 0;

    final private int index;

    final private static ArrayList<Task> tasks = new ArrayList<>();

    /**
     *
     */
    public Task() {
        index = threadNumber++;
        tasks.add(this);
    }


    private int nextIndex() {
        return (index + 1) % threadNumber;
    }

    @Override
    public void run() {

        try {

            for(int i = 0; i<10; i++){

                double dure = Math.random()*200 ;
                sleep((long) dure);

                synchronized (indexToPrint) {
                    while (indexToPrint.get() != index) {
                        indexToPrint.wait();
                    }
                    indexToPrint.set(nextIndex());
                    System.out.println(Thread.currentThread().getName());
                    indexToPrint.notifyAll();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}