您的位置:首页 > 编程语言 > Java开发

java多线程同步案例之--生产者消费者模型

2016-03-24 00:51 435 查看
需求:
1 同一时间内只能有一个生产者生产    

2 同一时间内只能有一个消费者消费    

3 生产者生产的同时消费者不能消费    

4 消费者消费的同时生产者不能生产 

 消费者和生产者只能有一个在工作。
 ----同步方法或者同步代码快
5 共享空间空时消费者不能继续消费    

6 共享空间满时生产者不能继续生产    

注意:
1、Wait、notify、notifyAll方法的调用必须放在同步方法和同步代码块里面
是调用“同步锁”对象的Wait、notify、notifyAll方法而不是线程对象的方法。
//定义一个仓库类

public class Storage {

    /**

     * Max_num表示仓库的最大容量

     * cur_num表示当前仓库的库存

     */

    static int Max_num = 100;

    

    private int cur_num = 50;

    

    //入库的方法
    public synchronized void in(int num){

//如果当前库存加上生产者准备存放的量大于仓库的最大容量,则将该线程挂起,释放当前进程锁

        while(this.cur_num + num > Max_num){

            try {

                System.out.println(Thread.currentThread().getName() + "入库失败,仓库已溢出!请及时消费");

                this.wait();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        this.notify();

        cur_num += num;

        System.out.println(Thread.currentThread().getName() + "入库" + num +",库存为:" + cur_num);

    }

    

    //出库的方法
    public synchronized void out(int num){

//如果当前消费者的需求量大于仓库的库存,则将该线程挂起,释放当前进程锁

        while(num > cur_num){

            try {

                System.out.println( Thread.currentThread().getName() + "出库失败,库存不足!请及时补货");

                this.wait();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

        this.notify();

        cur_num -= num;

        System.out.println(Thread.currentThread().getName() + "出库" + num +",库存为:" + cur_num);
    }

//接着定义消费者线程类

public class Customer extends Thread{

    Storage s; //根据仓库的对象实现线程同步

    private int num; //当前消费者的需求量

    

    /**

     * @param name 输出当前线程名(也就是消费者名)

     * @param s    传入仓库对象

     * @param num 消费者的需求量

     */

    public Customer(String name,Storage s,int num){

        super(name);//线程名

        this.s = s;

        this.num = num;

    }

    

    public void run(){

        try {

            Thread.sleep(500);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        //调用仓库中的出库方法,将需求变量传入

        s.out(num);

    }

}

//还需定义一个生产者线程类

public class Producer extends Thread{

    Storage s; //根据仓库的对象实现线程同步

    private int num;//当生产者的生产量

    /**

     * @param name 输出当前线程名(也就是生产者名)

     * @param s    传入仓库对象

     * @param num 生产者的生产量

     */

    public Producer(String name,Storage s,int num){

        super(name); //线程名

        this.s = s;

        this.num = num;

    }

    

    public void run(){

        try {

            Thread.sleep(500);

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

        //调用仓库中的入库方法,将准备入库的数量传入

        s.in(num);

    }

}

//最后,创建Test类进行测试

public class Test {

    public static void main(String[] args) {

        //创建一个共同的仓库对象(注:这里因为是消费者线程和生产者线程要实现同步,所以只能new一个仓库对象)

        Storage s = new Storage();

        

        //创建生产者线程:

        /**

         * 传入线程名、对象、出入库的数量

         */

        Producer p1 = new Producer("P_1", s, 50);

        Producer p2 = new Producer("P_2", s, 20);

        Producer p3 = new Producer("P_3", s, 30);

        

        //创建消费者进程:

        Customer c1 = new Customer("C_1", s, 60);

        Customer c2 = new Customer("C_2", s, 30);

        Customer c3 = new Customer("C_3", s, 60);

        //启动线程

        p1.start();p2.start();p3.start();

        c1.start();c2.start();c3.start();      

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: