简体   繁体   中英

Printing Odd and Even number using 2 threads?

I have tried this code. But after printing 0 , it doesn't print anything. It is blocking due to some lock I think.

public class EvenOdd implements Runnable {
    private Object o = new Object();
    private volatile int i = 0;

    public void run() {
        try {
            System.out.println();
            if ( Thread.currentThread().getName().equals( "Even")) {
                printEven();
            } else {
                printOdd();
            }
        } catch ( Exception ee) {
            ee.printStackTrace();
        }
    }

    private void printEven() throws InterruptedException {
        while ( true) {
            synchronized ( o) {
                while ( this.i % 2 == 0) {
                    o.wait();
                }
                System.out.println( Thread.currentThread().getName() + i);
                i++;
                o.notify();
            }
        }
    }

    private void printOdd() throws InterruptedException {
        while ( true) {
            synchronized ( o) {
                while ( this.i % 2 != 0) {
                    o.wait();
                }
                System.out.println( Thread.currentThread().getName() + i);
                i++;
                o.notify();
            }
        }
    }
}

My TestClass:

EvenOdd x = new EvenOdd();
        new Thread(x,"Even").start();
        new Thread(x,"Odd").start();

Where am I wrong? Thank.

PS : I know this type of question has been asked many times , but I want to try by my own.

My guesses is you are;

  • using one Runnable but both of then think they are even ie they both see the first value of 0
  • printEven has to wait for an odd number ad printOdd has to wait for an even number

EDIT: After running the code the OP fixed the code, it prints

0
1

as expected. It may sometimes print 0 and 0 randomly as the first check for odd/even is not synchronized.

It's a simple deadlock:

Thread 1 waits for someone to notify on the lock. Thread 2 waits for someone to notify on the same lock.

Since no one ever gets to o.notify(); , nothing happens.

And i is 0 when both threads start, so both first call printEven() . Now when that has happened, both threads will then call printOdd() in the next round.

The basic concept is when one thread is running, the other has to wait. Once the thread prints the value, it has to wait until the other thread prints. This is achieved by using wait/notify mechanism.

When Odd thread completes printing the value, it notifies the waiting thread(Even thread) and the Even thread becomes ready to run but will wait for the lock to be released by the Odd thread. Now the odd thread calls wait on the locker object so that it releases the lock and goes to wait state. At this point, the only thread waiting for locker object's lock is Even thread and it runs. This process continues alternatively.

public class Test {
    public static void main(String[] args) {
        Object locker = new Object();
        Thread t1 = new Thread(new OddWorker(locker));
        Thread t2 = new Thread(new EvenWorker(locker));
        t1.start();
        t2.start();

    }
}

class OddWorker implements Runnable {
    private Object locker;
    private int number = 1, count = 1;

    OddWorker(Object locker) {
        this.locker = locker;
    }

    @Override
    public void run() {
        synchronized (locker){
            do {
                try {
                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number += 2;
                    locker.notify();
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while(++count < 11);
            locker.notify();
        }
    }
}

class EvenWorker implements Runnable {
    private Object locker;
    private int number = 2, count = 1;

    EvenWorker(Object locker) {
        this.locker = locker;
    }

    @Override
    public void run() {
        synchronized (locker){
            do {
                try {
                    System.out.println(Thread.currentThread().getName() + ": " + number);
                    number += 2;
                    locker.notify();
                    locker.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while(++count < 11);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM