生产者与消费者模型

本文深入探讨了生产者与消费者模型,揭示了在多线程环境下可能出现的资源强夺问题。通过代码示例展示了如何利用对象的wait()方法避免并发访问冲突,并解释了在解决此类问题时如何正确唤醒等待的线程。
摘要由CSDN通过智能技术生成

本文主要内容:

(1)生产者与消费者模型

1.生产、消费者模型

public class House {
    private ArrayList<String> list = new ArrayList<>();
    //向集合中添加元素的方法
    public void add(){
        if(list.size()<20){
            list.add("a");
        }else {
            return;
        }
    }
    //从集合中取元素
    public void get(){
        if(list.size()>0){
            list.remove(0);
        }else {
            return;
        }
    }
}
public class Producer extends Thread {
    private House house;
    public Producer(House house){
        this.house = house;
    }
    public void run(){
        while (true){
            house.add();
            System.out.println("生产者存入一件货物");
        }
    }
}
public class Customer extends Thread {
    private House house;
    public Customer(House house){
        this.house = house;
    }
    public void run(){
        while (true){
            house.get();
            System.out.println("消费者取出了一件货物");
        }
    }
}
public class TestMain {
    public static void main(String[] args) {
        House house = new House();
        Producer p = new Producer(house);
        Customer c1 = new Customer(house);
        Customer c2 = new Customer(house);
        Customer c3 = new Customer(house);
        p.start();
        c1.start();
        c2.start();
        c3.start();
    }
}
//代码中return不是很好,应该让线程的不同状态来回切换

(1)通过以下代码,成功的演示了线程安全的问题,两个消费者同时访问同一个仓库对象,仓库内只有一个元素时,两个消费者并发访问,会有可能产生强夺资源的问题。

public class House {
    private ArrayList<String> list = new ArrayList<>();
    //向集合中添加元素的方法
    public void add(){
        if(list.size()<20){
            list.add("a");
        }else {
            return;
        }
    }
    //从集合中取元素
    public void get(){
        if(list.size()>0){
            list.remove(0);
        }else {
            return;
        }
    }
}
public class Producer extends Thread {
    private House house;
    public Producer(House house){
        this.house = house;
    }
    public void run(){
        while (true){
            house.add();
            System.out.println("生产者存入一件货物");
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Customer extends Thread {
    private House house;
    public Customer(House house){
        this.house = house;
    }
    public void run(){
        while (true){
            house.get();
            System.out.println("消费者取出了一件货物");
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class TestMain {
    public static void main(String[] args) {
        House house = new House();
        Producer p = new Producer(house);
        Customer c1 = new Customer(house);
        Customer c2 = new Customer(house);
        Customer c3 = new Customer(house);
        p.start();
        c1.start();
        c2.start();
        c3.start();
    }
}
//运行结果会报错
//java.lang.ArrayIndexOutOfBoundsException: -1
//	at java.util.ArrayList.add(ArrayList.java:459)
//	at com.xiancheng.House.add(House.java:14)
//	at com.xiancheng.Producer.run(Producer.java:14)
//代码中return不是很好,应该让线程的不同状态来回切换

(2)解决以上的问题

public class House {
    private ArrayList<String> list = new ArrayList<>();
    //向集合中添加元素的方法
    public void add(){
        if(list.size()<20){
            list.add("a");
        }else {
            try {
                this.wait();//仓库调用wait(),不是仓库对象等待,而是调用仓库生产者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //从集合中取元素
    public void get(){
        if(list.size()>0){
            list.remove(0);
        }else {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//Producer、Customer、TestMain的方法如上代码
//运行结果
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
消费者取出了一件货物
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at com.xiancheng.House.get(House.java:29)
	at com.xiancheng.Customer.run(Customer.java:14)
java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at com.xiancheng.House.get(House.java:29)
	at com.xiancheng.Customer.run(Customer.java:14)

(2-1)对象.wait():不是当前的这个对象wait,而是访问这个对象的线程wait()
(2-2)上述代码会出现异常,是应为所有的线程都进入了等待状态,没有线程做事,所以需要将所有的线程唤醒,代码如下:

public class House {
    private ArrayList<String> list = new ArrayList<>();
    //向集合中添加元素的方法
    public void add(){
        if(list.size()<20){
            list.add("a");
        }else {
            try {
                this.notifyAll();
                this.wait();//仓库调用wait(),不是仓库对象等待,而是调用仓库生产者线程进入等待状态
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //从集合中取元素
    public void get(){
        if(list.size()>0){
            list.remove(0);
        }else {
            try {
                this.notifyAll();
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//Producer、Customer、TestMain类如上
//运行结果
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
消费者取出了一件货物
	at java.lang.Object.notifyAll(Native Method)
	at com.xiancheng.House.get(House.java:30)
	at com.xiancheng.Customer.run(Customer.java:14)
java.lang.IllegalMonitorStateException
	at java.lang.Object.notifyAll(Native Method)
	at com.xiancheng.House.get(House.java:30)
	at com.xiancheng.Customer.run(Customer.java:14)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值