public class Solution {
    public volatile static int COUNT = 4;

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < COUNT; i++) {
            new SleepingThread();
            SleepingThread.currentThread().join(40);
        }
    }

    public static class SleepingThread extends Thread {
        private static volatile int threadCount = 0;
        private volatile int countDownIndex = COUNT;

        public SleepingThread() {
            super(String.valueOf(++threadCount));
            start();
        }

        public void run() {
            while (true) {
                System.out.println(this);
                if (--countDownIndex == 0) return;
                if (currentThread().isInterrupted()) System.out.println("Нить прервана");
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                }
            }
        }

        public String toString() {
            return "#" + getName() + ": " + countDownIndex;
        }
    }
}
Если убрать параметр 40 у join, то программа просто зависает. Хотя, как я понял, должна ждать завершения нити и запускать следующую. Ну и, конечно, задача с таким решением не принимается.