难以理解Interthread通信

时间:2014-05-27 15:55:00

标签: java multithreading wait notify

任何人都可以通过线程间通信解释这个程序吗?

//生产者和消费者的正确实现。

class Q {
    int n;
    boolean valueSet = false;
    synchronized int get() {
        while(!valueSet)
            try {
                wait();
            } catch(InterruptedException e) {
                System.out.println("InterruptedException caught");
            }
        System.out.println("Got: " + n);
        valueSet = false;
        notify();
        return n;
    }
    synchronized void put(int n) {
        while(valueSet)
            try {
                wait();
            } catch(InterruptedException e) {
                System.out.println("InterruptedException caught");
            }
        this.n = n;
        valueSet = true;
        System.out.println("Put: " + n);
        notify();
    }
}

class Producer implements Runnable {
    Q q;

    Producer(Q q) {
        this.q = q;
        new Thread(this, "Producer").start();
    }
    public void run() {
        int i = 0;
        while(true) {
            q.put(i++);
        }
    }
}

class Consumer implements Runnable {
    Q q;
    Consumer(Q q) {
        this.q = q;
        new Thread(this, "Consumer").start();
    }
    public void run() {
        while(true) {
            q.get();
        }
    }
}

class PCFixed {
    public static void main(String args[]) {
        Q q = new Q();
        new Producer(q);
        new Consumer(q);
        System.out.println("Press Control-C to stop.");
    }
}

输出

投入:1 得到:1 投入:2 得到:2 放:3 得到:3 投入:4 得到:4 ......

就我而言,这是非常令人困惑的,尤其是使用notify()和wait()的put和get方法。还请解释为什么使用布尔值。

2 个答案:

答案 0 :(得分:1)

所以有2个主题。 Qne正在设置此Q数据结构的值,另一个正在读取它们。 Q使用布尔标志来判断是否存在新值,一旦读取现有值,该标志就会被清除。

Q.get使用wait来阻止,直到有一个新值可供读取。一旦它读取了新值,它就会将标志设置为false。

Q.put在将其设置为新值之前等待另一个队列读取新值,然后通过设置布尔标志并调用notify来让其他线程知道。

请记住,等待放弃锁定,以便其他线程可以获取它。

需要布尔标志,因为线程可能会在没有得到通知的情况下停止等待。仅仅因为一个线程醒来并不意味着它得到了通知。此外,即使线程得到通知,由于线程在开始等待时放弃锁定,事物的当前状态是未知的(通常有多线程程序,其中另一个线程可能潜入并在线程之间阻塞某事被通知并且它可以重新获得锁定的时间)因此线程必须在锁定后再次重新测试该条件。

像wait和notify这样的构造是大型并发程序的构建块,因此在只有两个线程的小例子中,有些东西可能没有多大意义。

答案 1 :(得分:1)

基本上看它是使用同步方法的多线程通信。

这里简单的要求是

1)首先允许为制作人写作。

2)接下来允许为消费者阅读。

使用布尔标志valueSet控制。

在生产者意味着放Q的方法,逻辑就这样工作 如果valueSettrue意味着已经写完了,那么请把put方法称为线程等待。所以它要等到有人打电话通知。

当然,它不会继续进一步的逻辑并继续等待有人打电话通知。

来读者意味着Q的get(),

如果valueSetfalse意味着写入器正在执行,那么请让get方法调用thread等待。所以它要等到有人打电话通知。

所以一旦writer完成执行,它会在结束时调用notify,现在读取器线程会唤醒并开始读取。