代码拉取完成,页面将自动刷新
package ThreadStudy.notify;
/**
* wait() 表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁
* wait(long timeout) 指定等待的毫秒数
* notify() 唤醒一个处于等待状态的线程
* notifyAll() 唤醒同一个对象上所有调用wait()方法的线程,优先级别高的线程优先调度
*/
// 测试:生产者消费者模型 --> 利用缓冲区解决:管程法
// 生产者,消费者,产品,缓冲区
public class ProducerAndConsumer {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Producer(container).start();
new Consumer(container).start();
new Consumer(container).start();
}
}
//生产者
class Producer extends Thread{
SynContainer container;
public Producer(SynContainer container){
this.container = container;
}
//生产
@Override
public void run(){
for (int i = 0; i < 100; i++) {
container.push(new Chicken(i));
System.out.println("生产了" + i + "只鸡");
}
}
}
//消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container = container;
}
//消费
@Override
public void run(){
for (int i = 0; i < 100; i++) {
System.out.println("消费了-->" + container.pop().id + "只鸡");
}
}
}
//产品
class Chicken{
int id; //产品编号
public Chicken(int id) {
this.id = id;
}
}
//缓冲区
class SynContainer{
//需要一个容器大小
Chicken[] chickens = new Chicken[10];
//容器计数器
int count = 0;
//生产者放入产品
public synchronized void push(Chicken chicken){
//容器如果满了,就需要等待消费者消费
while (count == chickens.length){
//通知消费者消费,生产等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有满,我们就需要丢入产品
chickens[count] = chicken;
count++;
//可以通知消费者消费了
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop(){
//判断能否消费
while (count == 0){
//等待生产者生产,消费者等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// if (count == 0){
// //等待生产者生产,消费者等待
// try {
// this.wait();
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
//如果可以消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
/**
* 解释一:
* 在多线程中要测试某个条件的变化时(尤其是用于线程通信的条件判断)不要选
* 择if,而是选择while去判断。因为notify唤醒沉睡的线程后,线程会接着上次
* 的执行继续往下执行(需要注意的是,执行wait()的线程被notify唤醒的时候,
* 只是让while循环继续往下走,如果用if的话,继续往下走意味着跳出if语句块),
* 所以必须使用while循环阻塞。在本例中,如果管道中有一只鸡,那么第一个消费
* 者被唤醒去消费,消费了一只鸡之后,释放消费的锁,因为唤醒使用的是notifyAll,
* 所以是唤醒所有等待的线程再去由CPU决定把锁给谁,如果此时不是生产者拿到了锁
* 而是第二个消费者拿到锁,那么使用if的话则不会再做循环判断,会继续消费,从而造成数组下标越界。
*
* 解释二:
* 拿两个加法线程A、B来说,比如A先执行,执行时调用了wait方法,那它会等待,
* 此时会释放锁,那么线程B获得锁并且也会执行wait方法,两个加线程一起等待被唤醒。
* 此时减线程中的某一个线程执行完毕并且唤醒了这俩加线程,那么这俩加线程不会一起执行,
* 其中A获取了锁并且加1,执行完毕之后B再执行。如果是if的话,那么A修改完num后,
* B不会再去判断num的值,直接会给num+1。如果是while的话,A执行完之后,
* B还会去判断num的值,因此就不会执行。
*
* 以上解释那个易懂看哪个。
*
* 这是线程虚假唤醒的问题,总之,如果是多个生产者多个消费者的话,就是把push和pop里面的if都换成while
*/
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。