Java Threads等待,在一个类中通知给出意外结果

时间:2015-02-23 04:38:23

标签: java multithreading

/ 我写了下面的程序给wait()和notify()。但是在转到First put()方法之后,线程不会继续前进。任何人都可以解释一下我在下面的代码中做了什么错误。 /

public class ThreadJoin {
    public void buildThread() throws InterruptedException {
        Adder a = new Adder("Test");
        Thread t1 = new Thread(a, "First");
        Thread t2 = new Thread(a, "second");

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

    public static void main(String[] args) throws InterruptedException {
        new ThreadJoin().buildThread();
    }
}

class Adder implements Runnable {
    String name;
    int i;
    private boolean suspendFlag = false;

    public Adder(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
            for(int i = 0; i < 10; i++){
                put(i);
            }

            for(int j = 0 ; j < 10; j++){
                get();
            }
    }

    public synchronized void put(int i) {
        this.i = i;

        try {
            while (suspendFlag) {
                wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("put: " + i+" currentThread: "+Thread.currentThread().getName());
        suspendFlag = true;
        notify();
    }

    public synchronized void get() {
        System.out.println("Entering into the get method");

        try {
            if (!suspendFlag) {
                wait();
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("get: " + i+" currentThread: "+Thread.currentThread().getName());
        suspendFlag = true;
        notify();
    }
}

2 个答案:

答案 0 :(得分:2)

首先执行哪个线程(比如说First)将执行synchronized put方法,锁定Adder对象的监视器。发生这种情况时,另一个线程(second)无法开始执行put方法,因为它无法锁定同一Adder对象的监视器。

因此First看到suspendFlagfalse,因此会跳过while。它会supsedFlag true并调用notify()。目前Adder对象上没有线程等待,因此对notify()的调用不执行任何操作。

当此线程结束put方法的执行时,监视器将被释放,second可能会获取它。如果发生这种情况,则会看到suspendFlagtrue并进入while块,执行wait()。这样做,它会释放显示器。 suspendFlag仍为true

执行返回Firstfor循环put并重新调用suspendFlag。它看到truewhile并进入wait()循环,并调用wait

现在你的两个帖子都在notify,并且{{1}}没有任何内容。你的程序停滞不前。

答案 1 :(得分:1)

正在进行的简单视图是您有一个等待通知结构,强制执行putget次呼叫。你有两个线程,每个线程在它的第一个put之前将进行10 get个调用,因此无法进行交替。这两个主题最终都在put中等待另一个执行get

您可以将设计更改为允许多个put来电,而不是get,或更改驱动代码,以便一个主题执行put个调用而另一个执行get {{1}}调用