黑马程序员技术交流社区

标题: 问题已经解决线程方法使用在同步中的疑惑 [打印本页]

作者: 郑彬    时间: 2012-8-15 23:27
标题: 问题已经解决线程方法使用在同步中的疑惑
本帖最后由 郑彬 于 2012-8-17 23:19 编辑

r.wait();冻结
r.notify();叫醒(默认叫醒系统中前面冻结的那一个线程)
r.notifyAll();叫醒所有的线程
以上3种方法。都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
解释看不懂,能解释一下为什么吗?
作者: 杨彪    时间: 2012-8-15 23:35
举例:抓人游戏。
             定位,定住:其实就是wait
             被人拍醒:其实就是notify
           所有被抓的人都定住了,然后,说重玩:其实就是notifyAll
如果你玩过就应该明白
作者: 周兴华    时间: 2012-8-15 23:39
下图也许会方便你的理解:

作者: 周兴华    时间: 2012-8-15 23:52
一个比较经典的问题:生产者/消费者问题,这个问题的解决就是通过灵活使用wait()、notifyALL()方法实现的。
问题描述:
生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员就会叫生产者等一下,如果店中有空位放产品了再通知消费者来取走产品。这里可能出现的问题有一下两个:
1、生产者比消费者快时,消费者会漏掉一些数据没有取到
2、消费者比生产者快时,消费者会取相同的数据
一下代码就是解决方案:
//生产者消费者问题
public class ProductTest {

        public static void main(String[] args) {
                Clerk clerk = new Clerk();
                // 生产者线程
                Thread producerThread = new Thread(new Producer(clerk));
                // 消费者线程
                Thread consumerThread = new Thread(new Consumer(clerk));

                producerThread.start();
                consumerThread.start();
        }
}

// 店员
class Clerk {
        // 默认为0个产品
        private int product = 0;

        // 生产者生产出来的产品交给店员
        public synchronized void addProduct() {
                if (this.product >= 20) {
                        try {
                                // 产品已满,请稍候再生产
                                wait();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                } else {
                        product++;
                        System.out.println("生产者生产第" + product + "个产品");
                        // 通知等待区的消费者可以取产品了
                        notifyAll();
                }
        }

        // 消费者从店员处取产品
        public synchronized void getProduct() {
                if (this.product <= 0) {
                        try {
                                // 缺货,请稍候再取
                                wait();
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                } else {
                        System.out.println("消费者取走了第" + product + "个产品");
                        product--;
                        // 通知等待区的生产者可以生产产品了
                        notifyAll();
                }
        }
}

class Producer implements Runnable {
        private Clerk clerk;

        public Producer(Clerk clerk) {
                this.clerk = clerk;
        }

        public void run() {
                System.out.println("生产者开始生产产品");
                while (true) {
                        try {
                                Thread.sleep((int) (Math.random() * 10) * 100);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                        // 生产产品
                        clerk.addProduct();
                }
        }
}

class Consumer implements Runnable {
        private Clerk clerk;

        public Consumer(Clerk clerk) {
                this.clerk = clerk;
        }

        public void run() {
                System.out.println("消费者开始取走产品");
                while (true) {
                        try {
                                Thread.sleep((int) (Math.random() * 10) * 100);
                        } catch (InterruptedException e) {
                                e.printStackTrace();
                        }
                        // 取产品
                        clerk.getProduct();
                }
        }
}
作者: 郑彬    时间: 2012-8-17 23:19
问题已经解决




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2