Search code examples
javamultithreadingconcurrency

Print numbers sequentially using two threads


This an interview question and i don't think it has any relation with practical real life problems. I have to print numbers 12345.... sequentially but the condition is i have to print it using two threads one responsible for printing odd numbers and one for even numbers.
till now i have come up with this solution.

    package junk.concurrency;

public class PrintEvenOddTester {

    public static void main(String... args) {
        TaskEvenOdd t = new TaskEvenOdd(10);
        Thread t1 = new Thread(t, "odd printer");
        Thread t2 = new Thread(t, "even printer");
        t1.start();
        t2.start();
    }
}

class TaskEvenOdd implements Runnable {

    private int max;
    private boolean isOdd = true;
    private int number = 1;

    TaskEvenOdd(int max) {
        this.max = max;
    }

    synchronized void printEven(int number) { // sync on runnable itself

        while (isOdd) { // if odd is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Even:" + this.number);  // LINE-1
        isOdd = true;
        this.number++;                             // LINE-2
        notifyAll();
    }

    synchronized void printOdd(int number) { // sync on runnable itself
        while (!isOdd) { // if even is to be printed, wait
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Odd:" + this.number);    // LINE-3
        this.number++;                               // LINE-4
        isOdd = false;
        notifyAll();
    }

    @Override
    public void run() {

        while (number <= max) {

            if (Thread.currentThread().getName().equals("even printer")) {
                printEven(number);
            } else {
                printOdd(number);
            }
        }
    }
}

1
while writing this code i observed one strange behaviour which i did not understand. If at LINE-1,2,3,4 in above code, i write number instead of this.number my number instance variable is not getting incremented and code just prints infinite number of 1s.
I assume both the printEven and printOdd method is called on runnable instance itself then why its value is not getting incremented. I tried making number volatile but still it resulted in same output.
2
Also i see numbers are getting printed till 11 not till 10. I understand why this is happening(as the last call to printOdd gets notified by last call of printEven(which is printing 10) thus prints 11 ), one way to avoid this is to check number every time before printing and see if it's under limit but i wanted to know what would be the best way to overcome this.
Thanks.


EDIT method parameter number is completely redundant and can be omitted. This if(this.max>=number) condition can be used before printing the number.


Solution

  • 1

    Your problem is that the parameter of your method is called number too. So it is shadowing the field of your class! So, when you omit, you inc the parameter; which simply doesn't have any real effect!

    There are two solutions to this problem:

    1. Simply avoid doing it (so, by convention avoid using the same names as parameters and fields).

    2. Use tooling that spots such problems and tells you about. For example, findbugs has explicit rule to tell you about shadowing. And probably IDE's can be told to warn about this, too. See here.

    2

    Given the fact that this is just a "simple" assignment ... in my opinion a simple check for the "limit" of the overall class would be just fine.