Print Numbers with Two Threads (Odd and Even)
Problem
Read n. One thread prints the odd numbers and another thread prints the even numbers from 1 to n. The output must be in the correct order: 1, 2, 3, ..., n, one number per line.
Constraints
- 1 <= n <= 1000
Examples
Input
5
Output
1 2 3 4 5
Solutions
Two threads must take turns. A shared lock with wait and notify lets a thread sleep when it is not its turn, and wakes it up when the other thread has printed.
/*
* Problem : Print in order with two threads.
* Input : One integer n.
* Output : The numbers 1 to n.
* Approach: wait and notify.
* Time : O(n)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method prints the numbers with the given parity (1 = odd, 0 = even). It waits when it is not its turn.
static void printNumbers(Object lock, int[] next, int limit, String[] output, int parity) {
synchronized (lock) {
while (next[0] <= limit) {
if (next[0] % 2 == parity) {
output[next[0] - 1] = String.valueOf(next[0]);
next[0]++;
// Wake up the other thread.
lock.notifyAll();
} else {
try {
// Not my turn. Sleep until the other thread notifies.
lock.wait();
} catch (InterruptedException error) {
Thread.currentThread().interrupt();
return;
}
}
}
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(long n) {
// Step 1: A shared object (lock) is used for wait and notify. "next" is the next number to print.
final Object lock = new Object();
final int[] next = {1};
final int limit = (int) n;
final String[] output = new String[limit];
// Step 2: Both threads run the same code. A thread prints only when the next number has its parity (odd or even).
Runnable odd = () -> printNumbers(lock, next, limit, output, 1);
Runnable even = () -> printNumbers(lock, next, limit, output, 0);
Thread oddThread = new Thread(odd);
Thread evenThread = new Thread(even);
oddThread.start();
evenThread.start();
// Step 3: Wait until both threads are finished.
try {
oddThread.join();
evenThread.join();
} catch (InterruptedException error) {
Thread.currentThread().interrupt();
}
return output;
}
public static void main(String[] args) {
long n = new Scanner(System.in).nextLong();
System.out.println(String.join("\n", solve(n)));
}
}
Hints (2)
- What does wait() do to a thread?
- Who calls notify?