Printing Even and Odd Using Two Threads in Java

Printing Even and Odd using two Threads in Java

Found the solution. Someone looking for solution to this problem can refer :-)

public class PrintEvenOddTester {

public static void main(String... args) {
Printer print = new Printer();
Thread t1 = new Thread(new TaskEvenOdd(print, 10, false));
Thread t2 = new Thread(new TaskEvenOdd(print, 10, true));
t1.start();
t2.start();
}

}

class TaskEvenOdd implements Runnable {

private int max;
private Printer print;
private boolean isEvenNumber;

TaskEvenOdd(Printer print, int max, boolean isEvenNumber) {
this.print = print;
this.max = max;
this.isEvenNumber = isEvenNumber;
}

@Override
public void run() {

//System.out.println("Run method");
int number = isEvenNumber == true ? 2 : 1;
while (number <= max) {

if (isEvenNumber) {
//System.out.println("Even :"+ Thread.currentThread().getName());
print.printEven(number);
//number+=2;
} else {
//System.out.println("Odd :"+ Thread.currentThread().getName());
print.printOdd(number);
// number+=2;
}
number += 2;
}

}

}

class Printer {

boolean isOdd = false;

synchronized void printEven(int number) {

while (isOdd == false) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even:" + number);
isOdd = false;
notifyAll();
}

synchronized void printOdd(int number) {
while (isOdd == true) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Odd:" + number);
isOdd = true;
notifyAll();
}

}

This gives output like:

Odd:1
Even:2
Odd:3
Even:4
Odd:5
Even:6
Odd:7
Even:8
Odd:9
Even:10

Printing even and odd number using two threads

In this condition while (current % 2 != 0) (and opposite one in PrintEven) value of current is not updated. Use while (currentValue.getCurrent() % 2 != 0) instead; get rid of the current variable or update it in the loop.

print odd and even numbers using two threads in java efficiently?

You can do so in the following ways :

  1. Without using synchronization :

    class Print {

    private static int count = 1;
    private static int MAX = 20;
    private boolean isOdd = true;

    public void printEven() {
    while (true) {
    if (count > MAX) break;
    if (!isOdd) {
    System.err.println(Thread.currentThread().getName() + ":" + count++);
    isOdd = true;
    }
    }
    }

    public void printOdd() {
    while (true) {
    if (count > MAX) break;
    if (isOdd) {
    System.err.println(Thread.currentThread().getName() + ":" + count++);
    isOdd = false;
    }
    }
    }

    }

    public class ThreadOddEven {
    public static void main(String[] args) {
    Print p = new Print();

    // Thread t1 = new Thread(() -> p.printEven());
    Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
    p.printEven();
    }
    });
    t1.setName("EVEN");

    // Thread t2 = new Thread(() -> p.printOdd());
    Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
    p.printOdd();
    }
    });
    t2.setName("ODD");

    t1.start();
    t2.start();
    }

    }

    This is probably the most easiest way to achieve printing odd and
    even numbers across two threads.

    Here we are just using a boolean variable isOdd. This value gets
    toggled after each thread prints a value.

  2. Using synchronization :

    class Print2 {

    private static int count = 1;
    private static int MAX = 10;
    private Object obj = new Object();

    public void printEven() {
    while (true) {
    if (count > MAX) break;
    synchronized (obj) {
    System.err.println(Thread.currentThread().getName() + " : " + count++);
    obj.notify();
    try {
    obj.wait();
    } catch (InterruptedException e) { }
    }
    }
    }

    public void printOdd() {
    while (true) {
    if (count > MAX) break;
    synchronized (obj) {
    System.err.println(Thread.currentThread().getName() + " : " + count++);
    obj.notify();
    try {
    obj.wait();
    } catch (InterruptedException e) { }
    }
    }
    }

    }

    In the second example instead of using a boolean variable, we are
    using an object so that we can synchronize the calls between both
    threads.

    The main method call to this class is the same as the above example.

Print Even Odd number using two threads

Your problem is that you locking is too conservative/restrictive:

You put the lock around the whole loop; for both threads.

So, one thread gets into its loop; but quickly it can't progress. Because it would need that other thread to progress. But the second thread can't even start - because it can enter its loop at all!

In other words: in order to make progress; both threads need to be able to enter their respective loops; and make enough progress so that the other thread can do its next step.

Thats like building a room that only two person can exit together; but then you allow only one person to enter that room.

Welcome to multi-threaded programming; you just created your first dead-lock.

And for the record: when re-arranging the locks; make sure that you get the signaling right; so that wait/notify can work as supposed.

Finally: if you look carefully at your code; you will find that you duplicated a lot of code. That is always a bad idea. Instead: try to figure which parts are really different; and anything else ... should exist exactly once in your source code. So, as another exercise: when you re-arranged your code so that it does what it is supposed to do - try if you can refactor it, so that the amount of code duplication is minimized. I guarantee you, that will be an exercise worth spending your time on!

Create two threads, one display odd & other even numbers

I would just change a few details (no need to use the modulo operator here...):

public class Mythread {

public static void main(String[] args) {
Runnable r = new Runnable1();
Thread t = new Thread(r);
Runnable r2 = new Runnable2();
Thread t2 = new Thread(r2);
t.start();
t2.start();
}
}

class Runnable2 implements Runnable{
public void run(){
for(int i=0;i<11;i+=2) {
System.out.println(i);
}
}
}

class Runnable1 implements Runnable{
public void run(){
for(int i=1;i<=11;i+=2) {
System.out.println(i);
}
}
}

print even and odd using 2 threads

public class EvenOddPrinter {
static boolean flag = true;

public static void main(String[] args) {
class Odd implements Runnable {

@Override
public void run() {
for (int i = 1; i <= 10;) {
if (EvenOddPrinter.flag) {
System.out.println(i + "--->odd");
i += 2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}
}

}

class Even implements Runnable {

@Override
public void run() {
for (int i = 2; i <= 10;) {
if (!EvenOddPrinter.flag) {
System.out.println(i + "---->even");
i += 2;
EvenOddPrinter.flag = !EvenOddPrinter.flag;
}
}

}

}
Runnable odd = new Even();
Runnable even = new Odd();
Thread t1 = new Thread(odd, "Odd");
Thread t2 = new Thread(even, "Even");
t1.start();
t2.start();
}
}

Printing OddEven Number using 2 Threads in Java

There are some issues in your implementation regarding its design, generalization and general logic.

You're declaring two classes which basically do the exact same thing: printing numbers. The only thing that differs is the condition: whether the printed numbers must be odd or even. You could already achieve this with one Thread class, where the only thing to parameterize is the printing condition. The printOdd() and printEven() methods are almost a copy/paste.

Furthermore, the class responsibilities are not well dealt. Your SharedObject class is basically a counter, which not only keeps track and increments the counting value, but it has also to deal with both threads' logic, which is something that should not fall on it. Its sole goal should be to increment a shared value in a consistent way with parallel execution. You should redirect that printing logic within your Thread, since, as you can see, their code basically consists in making a single call.

Answer

Finally, the logic within your printOdd and printEven() methods has some loopholes. Both threads manage to print their corresponding number type only once at the start (the System.out.println without any text). This is because:

  1. One of the threads acquires the SharedObject's monitor, let's say OddThread, which means that EvenThread awaits OddThread to release the lock in order to enter the synchronized block. At this point, OddThread prints its corresponding number (1):
if (counter % 2 != 0) {
System.out.println(counter);
}

  1. Then, OddThread increments the value to 2, prints the notify statement and finally notifies the other thread (bear in mind that while the thread is doing all of this, it's still owning the SharedObject's monitor).
counter++;
System.out.println("OddThread: Notify: Counter: " + counter);
notify();

  1. Then, the loop ends and the while condition is tested. The fowllowing if fails as the number is now even and OddThread releases the lock and waits until it gets notified by EvenThread.
try {
System.out.println("OddThread: Wait: Counter: " + counter);
wait();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception!");
}

  1. Then, EvenThread can finally enter the synchronized statement and prints its value, which is 2.
if (counter % 2 == 0) {
System.out.println(counter);
}

  1. Then, it increments the value from 2 to 3, prints the notify statement with value 3 (so it's printing twice and the second time with an odd value even though it's the even thread) and finally notifies the other thread.
counter++;
System.out.println("EvenThread: Notify: Counter: " + counter);
notify();

  1. Then, EvenThread tests the while condition, fails the if statement, prints the waiting statement and then awaits for OddThread to awake it.
try {
System.out.println("EvenThread: Wait: Counter: " + counter);
wait();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception!");
}

  1. From now on, each thread will continue from their last wait() invocation. Both of them resume when the number is their right "type", but then they increment its value, making it their opposing type, and then printing the notify statement. This, not only explains why each thread prints their opposing number type, but it also explains why they keep printing even after the max value 10 has been reached. They both increment one more time after reaching the last while iteration since they both resume from their last wait() call.

Solution

Here is an implementation with all the design, generalization and logic loopholes fixed.

class Main {

public static void main(String[] args) {
SharedCounter counter = new SharedCounter();

ThreadPrintingNums oddThread = new ThreadPrintingNums("OddThread", counter, false, 10);
ThreadPrintingNums evenThread = new ThreadPrintingNums("EvenThread",counter, true, 10);

System.out.println("Starting Threads");

oddThread.start();
evenThread.start();
}
}

class ThreadPrintingNums extends Thread {

private SharedCounter counter;
private boolean flagPrintEven;
private int max;

public ThreadPrintingNums(String threadName, SharedCounter obj, boolean flagPrintEven, int max) {
setName(threadName);
this.counter = obj;
this.flagPrintEven = flagPrintEven;
this.max = max;
}

@Override
public void run() {
while (counter.getCounter() <= max) {
if (counter.getCounter() % 2 == (flagPrintEven ? 0 : 1)) {
System.out.printf("%s => %d%n", getName(), counter.getCounter());
counter.incCounter();
} else {
try {
synchronized (counter) {
counter.wait();
}
} catch (InterruptedException e) {
System.out.printf("%s interrupted exception", getName());
System.exit(-1);
}
}
}
}
}

class SharedCounter {

private int counter;

public SharedCounter() {
this.counter = 1;
}

public synchronized int getCounter() {
return counter;
}

public synchronized void incCounter() {
counter++;
notify();
}
}

Print odd and even using two threads in Java

Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for

public void printOdd() {
synchronized(this) {
...
}
}

where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.



Related Topics



Leave a reply



Submit