黑马程序员技术交流社区
标题:
问题已经解决线程方法使用在同步中的疑惑
[打印本页]
作者:
郑彬
时间:
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
下图也许会方便你的理解:
QQ截图20120815233831.png
(14.61 KB, 下载次数: 9)
下载附件
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