JAVA版本,線程四:線程實現賣票程序(加鎖,線程數據有順序,安全順序)

PS.名字什麼的不重要,改成了糖果,效果是一樣的。
不考慮順序的賣票線程程序,線程不安全模式
將票改成了糖果:


public class CandyDemo {
    public static void main(String[] args) throws IOException {
        //讀取配置文件:.properties
        Properties p = new Properties();
        //使用配置文件,可以隨時修改配置文件從而改變數據傳輸
        //路徑中沒有盤符,則默認在項目的目錄下,在項目默認路徑中添加文件,
        //文件內容爲    count=100
        p.load(new FileReader("count.properties"));
        //獲取票數
        String count = p.getProperty("count");
        //將糖的數量定下來,創建代表糖的類
        CandyNumber c = new CandyNumber();
        //添加100顆糖
        c.setCount(Integer.parseInt(count));
        //創建對象,代表四個小朋友
        //同時讓四個小朋友看到共享的一百顆糖
        Candys c1 = new Candys(c);
        Candys c2 = new Candys(c);
        Candys c3 = new Candys(c);
        Candys c4 = new Candys(c);
        //創建四個線程,代表小朋友的行爲
        //使用直接創建名字的構造方法,Thread類中,可以直接指定名字構造
        Thread t1 = new Thread(c1, "小明");
        Thread t2 = new Thread(c2, "小剛");
        Thread t3 = new Thread(c3, "小華");
        Thread t4 = new Thread(c4, "小萌");
        //開啓線程,活動開始
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

class Candys implements Runnable {
    //由於糖果總共只有一百顆,所以需要將總數定義爲公共使用數據,讓所有人公用這個數據
    //但是由於要共享數據,又要頻繁改值,並且線程執行沒有順序,
    // 所以static,會限定類的使用次數,每一次新建的類,調用的線程,都會使用static的數值,影響靈活性。
    //static int candy=100;      //無法優質的解決搶糖的順序問題,所以放棄這個
    //所以引入一個引用類型,來保證少糖的順序
    //注入CandyNumberd的類來當做屬性,實現靜態共享
    CandyNumber candy;

    //使用有參構造,來完成屬性的賦值
    //只要給定的參數一樣,則能保證每個線程創建的對象中的CandyNumber屬性是一樣的
    //由於類的對象是傳地址,所以當傳入參數相同的時候,就能保證他們使用的都是同一個candy
    public Candys(CandyNumber cnady) {
        this.candy = cnady;
    }
    @Override
    public void run() {
        //如果糖沒有搶完,就繼續活動
        boolean isCandy=true;
        while (isCandy) {
            //使用同步代碼塊鎖,鎖住核心代碼塊,在一個時間內,要執行完當前區域代碼,才能釋放CPU
            //synchronized (鎖對象)
            //鎖對象,就是指定程共享的鎖對象,被共享的對象就會在執行鎖住代碼區域中不會被搶佔
            //這個程序中一百個糖果是共享數據,所以要鎖定糖果對象candy
            synchronized (candy) {
                //如果已經沒有糖了,則放棄循環,直接結束活動
                if (candy.getCount() == 0) {
                    System.out.println("糖搶完了,活動結束,請左上角關注+1");
                    //糖搶完了,則跳出循環
                    isCandy=false;
                    break;
                }
                //搶走一顆糖,就糖減一
                candy.setCount(candy.getCount() - 1);
                //通告誰拿到了糖,還剩多少糖
                //使用Thread.currentThread()--放回當前正在執行的線程
                //使用getName()方法來返回線程名稱
                System.out.println(Thread.currentThread().getName()
                        + "搶到了糖,還剩" + candy.getCount() + "顆糖……");
            }
        }
   }
}
class CandyNumber {
    //代表糖的數量
    private int count;
    //由於要改變,所以提供方法
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}

運行結果:
在這裏插入圖片描述
JAVA版,線程初級入門案例一:繼承Thread類創建線程
JAVA版線程基礎案例二:實現Runnable完成線程
JAVA版本,線程三:線程實現賣票程序

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