3
public class EvenOddWithTwoThreads **extends Thread**
{
private volatile int count = 1;
private volatile boolean flag = false;
@Override
public void run() {
    while(count <=10){
        synchronized (this) {
            while(flag){
                flag= false;
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() +count);
            count= count+1;
            flag = true;

            notify();
        }
    }
}

public static void main(String[] args) {

    EvenOddWithTwoThreads ins = new EvenOddWithTwoThreads();
    **Thread t1 = new Thread(ins, "Odd Thread");**
    **Thread t2 = new Thread(ins,"Even Thread");**

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

    }
}

output:

Odd Thread1

Odd Thread2

Odd Thread3

Even Thread4

Odd Thread5

Even Thread6

Odd Thread7

Even Thread8

Odd Thread9

Even Thread10

public class EvenOddWithTwoThreads **implements Runnable**{

private volatile int count = 1;
private volatile boolean flag = false;


@Override
public void run() {
    while(count <=10){
        synchronized (this) {
            while(flag){
                flag= false;
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() +count);
            count= count+1;
            flag = true;

            notify();
        }
    }
}

public static void main(String[] args) {

    EvenOddWithTwoThreads ins = new EvenOddWithTwoThreads();
    Thread t1 = new Thread(ins, "Odd Thread");
    Thread t2 = new Thread(ins,"Even Thread");

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

    }
}

output :

Odd Thread1

Even Thread2

Odd Thread3

Even Thread4

Odd Thread5

Even Thread6

Odd Thread7

Even Thread8

Odd Thread9

Even Thread10

Null
  • 511
  • 5
  • 22
Rahul V.
  • 31
  • 3
  • check [this](http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread). – Null Jan 19 '17 at 08:10

1 Answers1

3

Extending Thread or implementing Runnable doesn't change the behaviour of your code, but in general it's better to use Runnable for the reasons explained here. The two piece of software you showed are equally bugged, it's just a coincidence that the second one is returning the right answer (I tried to run both on my machine and they are returning the right answer).

So, what's happening? At the beginning both threads are in the RUNNABLE state, so both can acquire the intrinsic lock (with the synchronization primitive). In your case it happens that Odd Thread acquire it first, so Even Threads goes in BLOCKED state. Odd Thread print his number and notify (no one in this case). At the end of the loop it releases the intrinsic lock and start the loop again. Now Even Thread is no more blocked by the lock, so both threads can try to acquire again the intrinsic lock: this is called Race Condition, meaning that the output is dependent on the timing with which the two threads are executed.

In the first case Even Thread is faster and acquire the lock, but since flag is now true it goes in WAITING state, releasing the lock that is used by Odd Thread to print "Odd Thread2" and notify Even Thread that goes in BLOCKED state (for further details see here). At the end of the loop Odd Thread release the lock and we are again in the same situation in which both threads can acquire the lock: in the worst case scenario Even Thread could always goes first and stay trapped in the while loop, waiting while Odd Thread does all the job.

Community
  • 1
  • 1
SimoV8
  • 1,382
  • 1
  • 18
  • 32
  • "equally bugged" is very imprecise language, neither `Runnable` nor `Thread` are 'bugged'. – Mark Rotteveel Jan 19 '17 at 09:11
  • Sorry, I meant the implementation above, I try to rephrase :) – SimoV8 Jan 19 '17 at 09:13
  • 1
    @RealSkeptic at the beginning I thought the same but actually it's not, because only one instance of `EvenOddWithTwoThreads` is created and passed to `new Thread` as a `Runnable` reference (`Thread` implements `Runnable` itself), so the two threads synchronize on the same object/lock. – SimoV8 Jan 19 '17 at 09:20
  • What I have been observing is that the first piece of code is never printing odd-even numbers alternatively, whereas with the second one it is almost all of the time. Why is it so? – Rahul V. Jan 19 '17 at 13:13
  • @RahulV. it's hard to say, thread scheduling is unpredictable and can depends on many factors. In your case, you're creating another thread instance `EvenOddWithTwoThreads` that is never started (actually you are passing the object to other two threads as a `Runnable` reference, you never call `start()` on `EvenOddWithTwoThreads`). This could cause the java scheduler to behave differently, explaining this phenomena. Nevertheless, you're design is broken and if it happens to work it doesn't mean it is correct because you can't (or should't) depend on such an undeterministic behaviour :) – SimoV8 Jan 19 '17 at 13:32
  • Is there any way through which by extending Thread, many threads can share the same object instance? – Rahul V. Jan 19 '17 at 13:33
  • You can create an external object that incapsulate the state and share it among many threads, being careful to synchronize appropriately. Anyway, as explained in the link I shared above, in your case it's probably better to implements Runnable instead of extends Thread. – SimoV8 Jan 19 '17 at 13:47
  • 1
    @RahulV. You should almost never override Thread, there are some exceptions, but almost always you should implement a `Runnable` instead and hand that to a normal `Thread` (or an executor service). – Mark Rotteveel Jan 19 '17 at 14:02