天天看点

线程经典案例

多线程的开发中有一个最经典的操作案例,就是生产者--》消费者, 生产者不断生产产品, 消费者不断取走产品。

例如:饭店里的一个厨师和一个服务员, 这个服务员必须等待厨师准备好膳食。当厨师准备好时,他会通知服务员,之后服务员上菜,然后返回继续等待。 这是一个任务协作的实例, 厨师代表生产者, 而服务员代表消费者。

火车票售卖: 在春运的时候, 火车可以通过网上购票和人工窗口购票的方式进行买票,  总票数固定, 各大窗口的票数根据这个总票数售卖,同一张票需被一个人购买, 不能同时一个人拥有同一个票,这是会发生打架的。票数要一致后, 在不同窗口售卖,就需要保证票数同步, 且同一张票只能由一个对象拥有, 不能同时售卖不同人。

package com.vince;

/**
 * 两个线程协同工作,先生产,再消费
 * 面试题
 * sleep 与 wait的区别
 * sleep :让线程进入休眠状态,让出cpu的时间片,不释放对象监视器的所有权(对象锁)
 * wait 让线程进入等待状态,让出cpu的时间片,并释放对象监视器的所有权,等待其他线程通过notify唤醒线程。
 */
public class ThreadDemo1 {
    public static void main(String[] args) {
        Food food = new Food();
        Producter p = new Producter(food);
        Customer c = new Customer(food);
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(c);
        t1.start();
        t2.start();
    }
}
    /**
     * 生产者
     */
    class Producter implements Runnable{
        private Food food;
        public Producter(Food food){
            this.food=food;
        }
        public void run(){
            for (int i = 0; i < 20; i++) {
                if(i%2==0){
                    food.set("锅包肉,酸甜口味","爽");
                }else{
                    food.set("佛跳墙,滋阴补阳","大补");
                }
            }
        }
    }

    /**
     * 消费者
     */
    class Customer implements Runnable{
        private Food food;
        public Customer(Food food){
            this.food=food;
        }
        public void run(){
            for (int i = 0; i < 20; i++) {
                food.get();
            }
        }
    }

    /**
     * 食物
     */
    class Food{
        private String name;
        private String desc;
        private boolean flag=true; //true表示可以生产,false表示可以消费
        /**
         * 生产产品
         */
        public  synchronized void set(String name,String desc){
            //不能生产
            if(!flag){
                try {
                    this.wait(); //线程进入等待状态,释放监视器的所有权(对象锁)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //设置菜名
            this.setName(name);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //设置菜的描述
            this.setDesc(desc);
            flag=false;
            this.notify(); //唤醒等待的线程(随机的其中一个)
        }

        /**
         * 消费产品
         */
        public synchronized void get(){
            //不能消费
            if(flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.getName()+"--->"+this.getDesc());
            flag=true;
            this.notify();
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        public String toString() {
            return "Food{" +
                    "name='" + name + '\'' +
                    ", desc='" + desc + '\'' +
                    '}';
        }

        public Food(String name, String desc) {
            this.name = name;
            this.desc = desc;
        }

        public Food() {
        }
    }

      

继续阅读