Google

Jul 18, 2013

Core Java multi-thread coding -- printing odd and even numbers with two threads



Q. Can you write code to print odd and even numbers by two threads in sequence?
A. Even though this is not a practical question, a handy beginner level question test your ability to write multi-threaded code.

Here are the considerations.

  • It needs to be atomic so that the numbers can be printed in sequence. You can use either the AtomicInteger class or maintain two boolean flags like oddPrinted and evenPrinted  to coordinate between the two threads.
  • Both threads need to have a lock to coordinate odd and even printing. In Java, every object has a lock. So, we can create a Object lock = new Object( ) as the lock for both threads to use.
  • The Java Object class has wait and notify/notifyAll methods to facilitate inter thread communication via the Object lock. The notify/notifyAll methods notify the waiting threads to get hold of the lock. Only one thread can execute the code snippet that is synchronized on the lock.
  • You need a main method that creates a main thread and then spawn two new threads to print odd and even numbers respectively. 
 Here is the sample code.

Step 1: The main thread class PrintOddEvenNumbersWithTwoThreads that spawns the two new threads via the thread pool.

  
package com.mycompany.app6;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * main thread
 */
public class PrintOddEvenNumbersWithTwoThreads
{
    public static void main(String[] args)
    {
        final int max = 10;
        final AtomicInteger i = new AtomicInteger(1); //start with 0
        Executor dd = Executors.newFixedThreadPool(2);
        
        final Object lock = new Object();
        
        //the main thread spawns two threads to print odd and even numbers respectively
        dd.execute(new OddNumber(max, i, lock));
        dd.execute(new EvenNumber(max, i, lock));
        
        do
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        
        while (i.get() != max + 1);
        
        System.out.println("\nDone");
        System.exit(0);
    }
}


Step 2: The OddNumber thread that prints odd numbers.

  
package com.mycompany.app6;

import java.util.concurrent.atomic.AtomicInteger;

public class OddNumber implements Runnable
{
    private int maxNumber;
    private AtomicInteger number;
    private Object lock;
    
    public OddNumber(int maxNumber, AtomicInteger number, Object lock)
    {
        this.maxNumber = maxNumber;
        this.number = number;
        this.lock = lock;
    }
    
    public void run()
    {
        print();
    }
    
    public void print()
    {
        while (number.get() < maxNumber + 1)
        {
            if (number.get() % 2 == 0)
            {
                System.out.println(Thread.currentThread().getName() + " --> " + number.getAndAdd(1));
                
                synchronized (lock)
                {
                    lock.notifyAll();//notify all waiting threads on this lock to resume 
                }
            }
            else
            {
                synchronized (lock)
                {
                    try
                    {
                        lock.wait(); //wait for the lock
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}



Step 3: The EvenNumber thread that prints even numbers. The implementation is very similar except for the boundary condition that checks for odd or even number.

  
package com.mycompany.app6;

import java.util.concurrent.atomic.AtomicInteger;

public class EvenNumber implements Runnable
{
    private int maxNumber;
    private AtomicInteger number;
    private Object lock;
    
    public EvenNumber(int maxNumber, AtomicInteger number, Object lock)
    {
        this.maxNumber = maxNumber;
        this.number = number;
        this.lock = lock;
    }
    
    public void run()
    {
        print();
    }
    
    public void print()
    {
        while (number.get() < maxNumber + 1)
        {
            if (number.get() % 2 != 0)
            {
                System.out.println(Thread.currentThread().getName() + " --> " + number.getAndAdd(1));
                
                synchronized (lock)
                {
                    lock.notify(); //notify all waiting threads on this lock to resume 
                }
            }
            else
            {
                synchronized (lock)
                {
                    try
                    {
                        lock.wait();  //wait for the lock
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}





Step 4: Run the main thread class PrintOddEvenNumbersWithTwoThreads to execute the code.

The output:

  
pool-1-thread-2 --> 1
pool-1-thread-1 --> 2
pool-1-thread-2 --> 3
pool-1-thread-1 --> 4
pool-1-thread-2 --> 5
pool-1-thread-1 --> 6
pool-1-thread-2 --> 7
pool-1-thread-1 --> 8
pool-1-thread-2 --> 9
pool-1-thread-1 --> 10

Done



There are other alternative approaches as described in the NumberGenerator class.

Labels: ,

1 Comments:

Blogger Sreenath said...

Nice example!!
small correction required to be more perfect!!
In EvenNumber class the condition should be if (number.get() % 2 == 0) and in OddNumber the condition should be if (number.get() % 2 != 0). Then it will print as below.


pool-1-thread-1 --> 1
pool-1-thread-2 --> 2
pool-1-thread-1 --> 3
pool-1-thread-2 --> 4
pool-1-thread-1 --> 5
pool-1-thread-2 --> 6
pool-1-thread-1 --> 7
pool-1-thread-2 --> 8
pool-1-thread-1 --> 9
pool-1-thread-2 --> 10

Done

8:03 PM, June 24, 2014  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home