2

I was attempting to solve a multi threaded problem and I am facing difficulties getting to know its behavior.

The problem is: There are 2 threads which simultaneously consume even and odd numbers. I have to introduce the thread communication between them to have the "consumption" in natural ordering.

here is my code

public class EvenOddDemo {

    public static void main(String[] args) {
        Number n = new Number();
        EvenThread et = new EvenThread(n);
        OddThread ot = new OddThread(n);
        et.start();
        ot.start();
    }

}

class EvenThread extends Thread {

    private Number number;

    public EvenThread(Number number) {
        this.number = number;
    }

    @Override
    public void run() {
        for(int i=0; i<5; i++) {
            System.out.println(number.getEven());
        }
    }


}

class OddThread extends Thread {

    private Number number;

    public OddThread(Number number) {
        this.number = number;
    }

    @Override
    public void run() {
        for(int i=0; i<5; i++) {
            System.out.println(number.getOdd());
        }
    }


}

class Number {

    private int currentEven = 0;

    private int currentOdd = 1;

    private volatile String last = "odd";

    public synchronized int getEven() {
        if("even".equals(last)) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int i = currentEven;
        last = "even";
        currentEven +=2;
        notify();
        return i;
    }

    public synchronized int getOdd() {
        if("odd".equals(last)) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int i = currentOdd;
        last = "odd";
        currentOdd +=2;
        notify();
        return i;
    }
}

and the output is

0
2
1
3
4
5
7
6
8
9

But when I debug the code, it prints the numbers in the correct order. Hence I am not able to figure out what I am missing. Please help me. Thanks in advance for your time for this thread.

4

3 回答 3

5

据我所知,没有什么可以阻止这种情况的发生,解释了为什么2之前1在输出中显示:

OddThread     EvenThread
----------    ----------
gets odd
              gets even
              prints even
prints odd

因此,锁需要围绕整个序列“获取/打印”。

您会注意到,您的输出中也永远不会“分开两个数字”。

于 2013-07-12T18:03:20.040 回答
2

notify选择任何可用的线程。

选择是任意的,并由实施自行决定

如果有两个以上的线程在等待,您可能会发出“错误”线程的信号。

另外,请注意,您的两个线程都可能刚刚在 get(Even|Odd) 中完成而没有等待,导致通知无处可去,具体取决于调度。

您需要更加严格以确保订购。也许两个锁,偶数和奇数,会有所帮助。

于 2013-07-12T17:55:24.603 回答
0

您需要在 getEven 和 getOdd 函数中打印数字并通知其他线程。但是你是在通知和打印号码,所以在 noti 之间 修改了代码:

public class ThreadExp {

    public static void main(String[] args) {
        Number n = new Number();
        EvenThread et = new EvenThread(n);
        OddThread ot = new OddThread(n);
        et.start();
        ot.start();
    }

}

class EvenThread extends Thread {

    private Number number;

    public EvenThread(Number number) {
        this.number = number;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            number.getEven();
        }
    }

}

class OddThread extends Thread {

    private Number number;

    public OddThread(Number number) {
        this.number = number;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            number.getOdd();
        }
    }

}

class Number {

    private int currentEven = 0;

    private int currentOdd = 1;

     private StringBuilder odd;
     private StringBuilder even;
     private StringBuilder last;

    {
        odd = new StringBuilder("odd");
        even = new StringBuilder("even");
        last = odd;
    }

    public synchronized void getEven() {
        if (last == even) {
            try {
                 //System.out.println("inside if in even--->" +Thread.currentThread());
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //System.out.println("out of if in even--> " + Thread.currentThread());
        int i = currentEven;
        last = even;
        currentEven += 2;
        System.out.println(i);
        notify();
        return;
    }

    public synchronized void getOdd() {
        if (last == odd) {
            try {
                //System.out.println("inside if in odd--->" +Thread.currentThread());
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //System.out.println("out of if in odd--> " + Thread.currentThread());

        int i = currentOdd;
        last = odd;
        currentOdd += 2;
        System.out.println(i);
        notify();
        return;
    }
}
于 2013-11-22T10:34:09.900 回答