Sourabh
Sourabh

Reputation: 680

Odd even number printing using thread

Odd even number printing using thread.Create one thread class, two instance of the thread. One will print the odd number and the other will print the even number.

I did the following coding. But it comes to dead lock state. Can some one please explain what might be the reason for that?

public class NumberPrinter implements Runnable{
private String type;
private static boolean oddTurn=true;


public NumberPrinter(String type){
    this.type=type;
}
public void run() {
    int i=type.equals("odd")?1:2;
    while(i<10){
        if(type.equals("odd"))
            printOdd(i);
        if(type.equals("even"))
            printEven(i);
        i=i+2;
    }

}

private synchronized void printOdd(int i){
    while(!oddTurn){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println(type + i);
    oddTurn=false;
    notifyAll();
}

private synchronized  void printEven(int i){
    while(oddTurn){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }
    }
    System.out.println(type + i);
    oddTurn=true;
    notifyAll();

}

public static void main(String[] s){
    Thread odd=new Thread(new NumberPrinter("odd"));
    Thread even=new Thread(new NumberPrinter("even"));
    odd.start();
    even.start();

}
}

Out Put: odd1 even2


then comes to deadlock!!!!!!

Thanks for your help.

Upvotes: 7

Views: 13818

Answers (13)

Rakesh Kumar
Rakesh Kumar

Reputation: 1

I implemented it in a very simple way, from 1 to 40>

public class EvenOddProblem {

    public static void main(String[] args) {
        Printer p = new Printer();
        EvenThread enenThread = new EvenThread(p);
        OddThread oddThread = new OddThread(p);
        new Thread(enenThread).start();
        new Thread(oddThread).start();

    }

}

class EvenThread implements Runnable {
    private Printer printer;

    public EvenThread(Printer p) {
        printer = p;
    }

    @Override
    public void run() {
        try {
            int i = 0;
            while (true) {
                if (i == 20)
                    break;
                i++;

                printer.evenPrintEven();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class OddThread implements Runnable {
    private Printer printer;

    public OddThread(Printer p) {
        printer = p;
    }

    @Override
    public void run() {
        int i = 0;
        try {
            while (true) {
                if (i == 20)
                    break;
                i++;
                printer.evenPrintOdd();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class Printer {
    private static volatile Integer i = 1;

    public synchronized void evenPrintOdd() throws InterruptedException {
        while (i % 2 == 0) {
            wait();
        }
        System.out.println(i);
        i++;
        notifyAll();
    }

    public synchronized void evenPrintEven() throws InterruptedException {
        while (!(i % 2 == 0)) {
            wait();
        }
        System.out.println(i);
        i++;
        notifyAll();
    }
}

Upvotes: 0

Hareesh M D
Hareesh M D

Reputation: 1

Program for Two Threads Alternatively Print Odd and Even Numbers.

#Implemented Using "Object Lock" Concept.

class Increment{
private int count;
    public void increment(){
        count++;
        System.out.println(Thread.currentThread().getName()+"::::::::::::::::::"+count);
    }
}


class SimpleThread extends Thread{
 
 Increment obj = null;
 
 SimpleThread(Increment obj){
    this.obj=obj;
 }  
 
 public void run(){
     try {
    Thread.sleep(100);
         while(true){
            synchronized(obj){
                   obj.increment();
                   Thread.sleep(1000);
                   obj.notify();
                   obj.wait();  
            }
         }
     } catch(InterruptedException ie) {
        ie.printStackTrace(); 
     }
 } 
 
}

public class Main
{
    public static void main(String[] args) {
        
        Increment increment = new Increment();
        SimpleThread t1 = new SimpleThread(increment);
        SimpleThread t2 = new SimpleThread(increment);
       
        t1.start();
        t2.start();

        System.out.println(Thread.currentThread().getName()+"::::::::::::::"+"Hello World");
        System.out.println(Runtime.getRuntime().availableProcessors()+"::::::::::::::"+"CORE SIZE");
    }
}

Upvotes: 0

Prasanna
Prasanna

Reputation: 2498

I have implemented in such a way, based on the argument, no of threads will be spawned and will the respective no in round robin manner. i.e., If thread count is 3, thread 1 will print 1,4 ...; thread 2 will print 2,5,... and thread 3 will print 3,6...

public class ThreadSynchronizer
{

    public static void main(String[] args)
    {
    // BASED ON THE ARGUMENT MULTIPLE THREADS WILL BE CREATED AND EACH WILL PRINT ITS RESPECTIVE NO
    // IE, IF THREAD COUNT IS 3, THREAD 1 WILL PRINT 1,4 ..., THREAD2 WILL PRINT 2,5,... AND THREAD3 WILL PRINT 3,6...
    // LIMITED THE DISPLAY TO 1000 NOS
    int threadCnt = Integer.parseInt(args[0]);

    ReentrantLock lckArray[] = new ReentrantLock[threadCnt + 1];

    for (int i = 0; i < threadCnt + 1; i++)
    {
        ReentrantLock lck = new ReentrantLock();
        lck.lock();
        lckArray[i] = lck;
    }

    for (int i = 0; i < threadCnt; i++)
    {
        Thread th = new Thread(new Printer(lckArray, i + 1));
        th.start();
    }

    for (int i = 1; i < threadCnt + 1; i++)
    {
        lckArray[i].unlock();

        while (!lckArray[i].isLocked())
        {

        }
    }
    lckArray[0].unlock();
    }
}

class Printer implements Runnable
{

    private ReentrantLock[] lckArray;
    private int index;

    Printer(ReentrantLock[] lckArray, int startValue)
    {
    this.lckArray = lckArray;
    this.index = startValue;
    }

    @Override public void run()
    {
    ReentrantLock prevLock = null;
    int printCounter = index;

    for (int counter = 0; printCounter <= 1000; counter++)
    {
        int remCounter = counter % lckArray.length;
        int incCounter = lckArray.length - remCounter;
        int indexPostion = index + incCounter;
        int curElementIndex = indexPostion % lckArray.length;

        lckArray[curElementIndex].lock();
        if (prevLock != null)
        prevLock.unlock();
        prevLock = lckArray[curElementIndex];

        if (curElementIndex == 0)
        {
        System.out.println("Printed by Thread " + index + " " + printCounter);
        printCounter = printCounter + lckArray.length - 1;
        }

    }

    if (prevLock != null)
    {
        if (prevLock.isHeldByCurrentThread())
        prevLock.unlock();
    }

    }

}

Upvotes: 0

sanket patel
sanket patel

Reputation: 499

public class Number_Thread extends Thread {

String thread;
int limit;

public Number_Thread(String thread,int limit){
    this.thread=thread;
    this.limit=limit;
                                             }

Object lock=new Object();

public  void run()
{

    synchronized (lock) 
    {

          //------------------- "print even"--------------------//

      if(thread.equals("even"))
        {
            for (int i = 2; i <=limit; i+=2) 
            {

                 System.out.println(thread+" thread "+i);
            try {

            lock.wait(1000);
                 continue;

                }
              catch (InterruptedException e) {}
            }
            lock.notifyAll();
        }

         //------------------- "print odd"--------------------//

    if(thread.equals("odd"))
         {
         for (int i = 1; i <=limit; i+=2) 
             {
                System.out.println(thread+" thread  "+i);
            try {

                lock.wait(1000);
                    continue;
                }
            catch (InterruptedException e) {}
            }
            lock.notifyAll();
         }
      }
   }
}

     //------------------thread creater class------------------//
import java.util.Scanner;

public class Main_Thread {
private static Scanner s;
    public static void main(String[] args) throws InterruptedException {
        System.out.print("enter limit:\t ");
        s=new Scanner(System.in);
    int n=s.nextInt();
     s.close();
    Thread t1=new Number_Thread("even",n);
    Thread t2=new Number_Thread("odd",n);
    t2.start();
    Thread.sleep(100);
    t1.start();

 }

}

output for limit 5:

enter limit: 5

odd thread 1

even thread 2

odd thread 3

even thread 4

odd thread 5

Upvotes: 0

vijayinani
vijayinani

Reputation: 2634

Your code corrected with using Lock interface:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NumberPrinter implements Runnable {
    private Lock lock;
    private Condition condition;
    private String type;
    private static boolean oddTurn = true;

    public NumberPrinter(String type, Lock lock, Condition condition) {
        this.type = type;
        this.lock = lock;
        this.condition = condition;
    }

    public void run() {
        int i = type.equals("odd") ? 1 : 2;
        while (i <= 10) {
            if (type.equals("odd"))
                printOdd(i);
            if (type.equals("even"))
                printEven(i);
            i = i + 2;
        }
    }

    private void printOdd(int i) {
        // synchronized (lock) {
        lock.lock();
        while (!oddTurn) {
            try {
                // lock.wait();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + " " + i);
        oddTurn = false;
        // lock.notifyAll();
        condition.signalAll();
        lock.unlock();
    }

    // }

    private void printEven(int i) {
        // synchronized (lock) {
        lock.lock();
        while (oddTurn) {
            try {
                // lock.wait();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + " " + i);
        oddTurn = true;
        // lock.notifyAll();
        condition.signalAll();
        lock.unlock();
    }

    // }

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        Thread odd = new Thread(new NumberPrinter("odd", lock, condition));
        Thread even = new Thread(new NumberPrinter("even", lock, condition));
        odd.start();
        even.start();
    }
}

Upvotes: 0

vijayinani
vijayinani

Reputation: 2634

The same can be solved using Lock interface:

NaturalOrder.java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NaturalOrder {

    public int currentNumber = 1;
    public boolean evenOdd = false;

    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public static void main(String[] args) {
        NaturalOrder naturalOrder = new NaturalOrder();
        Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        t1.start();
        t2.start();
    }
}

OddNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class OddNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != false) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (naturalOrder.currentNumber % 2 != 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = true;

            condition.signalAll();
        }
        lock.unlock();
    }
}

EvenNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class EvenNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != true) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (naturalOrder.currentNumber % 2 == 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = false;
            condition.signalAll();
        }
        lock.unlock();
    }
}

Upvotes: 2

shreyas K N
shreyas K N

Reputation: 155

Here's my solution without any waits or notify. wait() and notify()/notifyAll() ,
I dont see any reason to use them for this problem statement.

package threading;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EvenOddPrinting {

    int count=0;
    boolean isOdd = false;

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        EvenOddPrinting obj = new EvenOddPrinting();
        exec.submit(new EvenPrinter(obj));
        exec.submit(new OddPrinter(obj));
        exec.shutdown();



    }

}

class EvenPrinter implements Runnable{
    EvenOddPrinting obj;
    public EvenPrinter(EvenOddPrinting obj) {
        this.obj=obj;
    }

    @Override
    public void run() {
        while(obj.count < 100){
            if(!obj.isOdd){
                System.out.println("Even:"+obj.count);
                obj.count++;
                obj.isOdd = true;
            }
        }

    }
}


class OddPrinter implements Runnable{

    EvenOddPrinting obj;
    public OddPrinter(EvenOddPrinting obj) {
        this.obj = obj;
    }

    @Override
    public void run() {
        while(obj.count < 100){
            if(obj.isOdd){
                System.out.println("Odd:"+obj.count);
                obj.count++;
                obj.isOdd = false;
            }
        }
    }
}

Upvotes: 0

Dungeon Hunter
Dungeon Hunter

Reputation: 20623

i Used a shared object to control the order of execution

class Counter implements Runnable {
  int count;
  static Class cl = Counter.class;

  public synchronized void increment() {
        String tname = Thread.currentThread().getName();
        System.out.printf("%s: %d\n", tname, count++);
  }

  @Override
  public void run() {
        String tname = Thread.currentThread().getName();
        while (true) {

              increment();
              synchronized (Counter.class) {
                    try {
                          cl.notify();
                          cl.wait();
                    } catch (Exception e) {
                          e.printStackTrace();
                    }
              }

        }
  }
}

public class WaitNotify {
public static void main(String[] args) {
    Counter c = new Counter();
    Thread t1 = new Thread(c, "thread1");
    Thread t2 = new Thread(c, "thread2");
    t1.start();
    t2.start();
}
}

Upvotes: 0

Jignesh
Jignesh

Reputation: 565

I did this way

public class OddEven{
        public static void main(String[] args){
            Print o=new Print();
            Thread even=new Thread(new MyRunnable(2,o));
            Thread odd=new Thread(new MyRunnable(1,o));
            even.start();
            odd.start();
        }
}
class MyRunnable implements Runnable{
        int start;
        Print ob;
        MyRunnable(int s,Print o){
            start=s;
            ob=o;
        }
        public void run(){
            for(int i=start;i<=20;i+=2)
                ob.display(i);
        }   
}
class Print{
        int rem=0;
        synchronized void display(int n){
            while(n%2==rem)
                try{
                    wait();
                }
                catch(Exception e){System.out.println("Display interrupted");}
            System.out.print(n+" ");
            rem=n%2;
            notify();
        }           
}

Upvotes: 1

aioobe
aioobe

Reputation: 421180

You're waiting and notifying different objects (monitors).

The idea is that you can call obj.wait() to wait for someone to do obj.notify(), while you're doing objA.wait() and objB.notify().

Change your printOdd method to something like

private void printOdd(int i) {
    synchronized (lock) {                        // <-------
        while (!oddTurn) {
            try {
                lock.wait();                     // <-------
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + i);
        oddTurn = false;
        lock.notifyAll();                        // <-------
    }
}

and the printEven method similarly.

Then provide the NumberPrinter with a lock object:

Object lock = new Object();
Thread odd = new Thread(new NumberPrinter("odd", lock));
Thread even = new Thread(new NumberPrinter("even", lock));

Output:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9

Upvotes: 13

Aaron Digulla
Aaron Digulla

Reputation: 328770

There are a lot of bugs in the code.

First of all, the synchronized statements have no effect whatsoever. You create two thread instances, and each calls only its own methods. synchronized is only useful if another thread can call a method.

Then notifyAll() has no effect for the same reasons. odd.notifyAll() doesn't reach even hanging in the wait().

So what you need is another object which contains the state and which both threads can see and use. Use synchronized, wait() and notifyAll() on that third instance.

Upvotes: 4

Jan Zyka
Jan Zyka

Reputation: 17898

I think the problem might be that printOdd and printEven synchronize on different lock (the Thread's object instance locks). Therefor you have not guaranteed that the change on the static variable oddTurn will be visible in the other thread. Try to make the oddTurn volatile for the start.

Upvotes: 1

Vladimir Ivanov
Vladimir Ivanov

Reputation: 43108

You're missing volatile keyword within oddTurn variable. Without it there are no guarantees the threads see the actual value.

Upvotes: 0

Related Questions