Java生產者消費者問題

題目要求:
現在有一個果籃,裏面可以放置很多蘋果,編碼者作爲一個蘋果的生產者,負責向這個果籃中放置蘋果
提示:通過控制檯輸入的數字,決定每次放置到果籃的蘋果數。
現在有3個孩子作爲消費者,負責從這個果籃中每次去拿一個蘋果,然後吃掉
孩子A:吃蘋果需要3秒鐘
孩子B:吃蘋果需要2秒鐘
孩子C:吃蘋果需要4秒鐘
現在需要設計若干個類,並充分運用wait\sleep\notifyAll\synchronized滿足下述要求
①需要設計3個線程代表三個孩子去同步從果籃中獲取蘋果
②每個孩子需要等待生產者的通知,當生產者(編碼者)放置蘋果的時候,纔會去果籃中拿蘋果
③每個孩子拿完一個蘋果之後,會花一定的時間來吃蘋果,然後繼續從果籃中獲得蘋果,如果果籃爲空,進入等待生產者通知狀態
④生產者在向果籃放置蘋果的時候,根據控制檯輸入的數字決定放置蘋果的個數,並通知所有線程可以去拿蘋果

解析:

對於生產者消費者問題,要理清楚哪些資源是被併發訪問的,然後在此資源上加上適當的鎖就可以了。

import java.util.Scanner;

/**
 * 果籃類 
 * 1.果籃類是一個公共區域,生產者可以將蘋果放入果籃,消費者則可以從果籃中取走蘋果;
 * 2.要解決的問題是如何保證此果籃被多個生產者或者多個消費者併發訪問時的數據的完整性; 
 * 3.這裏解決的方法是使用同步鎖機制;
 * 
 * @author guocunlei
 * 
 */
public class FruitBasket {
    private static int appleNum = 0;
    
    public int getAppleNum() {
        return appleNum;
    }

    /**
     * 生產者生產蘋果
     * 
     * @throws InterruptedException
     */
    public synchronized void produce() throws InterruptedException {
        // 如果蘋果的數量不爲0,說明果籃裏還不爲空,就不必生產
        while (appleNum != 0) {
            System.out.println("果籃中的蘋果數量爲" + appleNum);
            this.wait();
        }
        // 如果爲空就提醒生產者生產
        @SuppressWarnings("resource")
        Scanner sc = new Scanner(System.in);
        System.out.println("輸入生產的蘋果數:");
        appleNum = sc.nextInt();
        System.out.println("生產者已生產" + appleNum + "個蘋果");
        // 此時喚醒所有等待的線程
        notifyAll();
    }

    /**
     * 消費者消費蘋果
     */
    public synchronized void consume(String customerName) throws InterruptedException {
        // 如果蘋果數量爲0,就進入等待狀態
        while (appleNum == 0) {
            System.out.println("果籃中的蘋果數量爲" + appleNum + "," + customerName + "正在等待生產者通知...");
            this.wait();
        }
        // 如果不爲0,就消費蘋果
        System.out.println(customerName + "正在嘗試獲取蘋果...");
        appleNum--;
        System.out.println(customerName + "獲取蘋果成功!此時果籃中的蘋果數爲" + appleNum);
        notifyAll();
    }
}
/*
 * 生產者類:此生產者主要負責生產蘋果
 */
public class ProduceThread extends Thread {
    private FruitBasket fb;
   
    public ProduceThread(FruitBasket fruitBasket) {
        this.fb = fruitBasket;
    }

    public void run() {
        try {
            //進行生產,並將生產的產品放進籃子
            fb.produce();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


/*
 * 消費者類
 */
public class CustomerThread extends Thread {
    private FruitBasket fb;
    // 消費者的名稱
    private String customerName;
    // 消費者消費產品所用的時間
    private long millisecond;

    public CustomerThread(FruitBasket fruitBasket, String customerName, long millisecond) {
        this.millisecond = millisecond;
        this.customerName = customerName;
        this.fb = fruitBasket;
    }

    @Override
    public void run() {

        try {
            while (true) {
                // 從果籃中拿出產品(消費產品)
                fb.consume(customerName);
                Thread.sleep(millisecond);
                System.out.println(customerName + "吃完了蘋果耗時" + millisecond / 1000 + "秒");
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}



public class Main {
    public static void main(String[] args) {
        FruitBasket fruitBasket = new FruitBasket();
        //生產者
        ProduceThread produceThread = new ProduceThread(fruitBasket);
        //三個消費者
        CustomerThread customerThread1 = new CustomerThread(fruitBasket, "孩子A", 3000);
        CustomerThread customerThread2 = new CustomerThread(fruitBasket, "孩子B", 2000);
        CustomerThread customerThread3 = new CustomerThread(fruitBasket, "孩子C", 4000);
        //開啓線程
        produceThread.start();
        customerThread1.start();
        customerThread2.start();
        customerThread3.start();
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章