天天看點

線程經典案例

多線程的開發中有一個最經典的操作案例,就是生産者--》消費者, 生産者不斷生産産品, 消費者不斷取走産品。

例如:飯店裡的一個廚師和一個服務員, 這個服務員必須等待廚師準備好膳食。當廚師準備好時,他會通知服務員,之後服務員上菜,然後傳回繼續等待。 這是一個任務協作的執行個體, 廚師代表生産者, 而服務員代表消費者。

火車票售賣: 在春運的時候, 火車可以通過網上購票和人工視窗購票的方式進行買票,  總票數固定, 各大視窗的票數根據這個總票數售賣,同一張票需被一個人購買, 不能同時一個人擁有同一個票,這是會發生打架的。票數要一緻後, 在不同視窗售賣,就需要保證票數同步, 且同一張票隻能由一個對象擁有, 不能同時售賣不同人。

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() {
        }
    }

      

繼續閱讀