Como garantir que dois threads que imprimem números pares ímpares mantenham primeiro a ordem ímpar e depois para esta implementação?

Criei dois trabalhos executáveis: PrintEvenNumbersJob e PrintOddNumbersJob e gerou dois threads para executar esses trabalhos. Isso parece funcionar perfeitamente bem! Mas sinto algo suspeito nesta implementação. Posso ter alguns comentários e conselhos sobre esta implementação?

O problema que vejo com essa implementação é que o programa termina apenas quando o thread1 obtém o bloqueio do objeto primeiro; caso contrário, imprime a primeira e a segunda ordem ímpares e não termina, a menos que forneça outra instrução "lock.notify" depois para declaração em PrintEvenNumbersJob (como nesta implementação). Minha pergunta aqui é como garantir que o thread1 seja executado primeiro.

public class PrintEvenNumbersJob implements Runnable {

private Object lock;

public PrintEvenNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 0; i <= 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify(); // not required if thread1 gains lock first
    }
}

}


public class PrintOddNumbersJob implements Runnable {

private Object lock;

public PrintOddNumbersJob(Object lock) {
    this.lock = lock;
}

@Override
public void run() {
    synchronized (lock) {
        for (int i = 1; i < 10; i += 2) {

            lock.notify();

            System.out.println(i);

            try {
                lock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        lock.notify();
    }
}

}



public class EvenOddManager {

public static void main(String[] args) {

    Object lock = new Object();

    PrintEvenNumbersJob printEvenNumbersJob = new PrintEvenNumbersJob(lock);
    PrintOddNumbersJob printOddNumbersJob = new PrintOddNumbersJob(lock);

    Thread thread1 = new Thread(printEvenNumbersJob);
    Thread thread2 = new Thread(printOddNumbersJob);

    thread2.start();
    thread1.start();

}

}

questionAnswers(3)

yourAnswerToTheQuestion