1. 程式人生 > 實用技巧 >你知道購買車票的原理嗎?Java 執行緒同步

你知道購買車票的原理嗎?Java 執行緒同步

先看再點贊,給自己一點思考的時間,如果對自己有幫助,微信搜尋【程式職場】關注這個執著的職場程式設計師。
我有什麼:職場規劃指導,技能提升方法,講不完的職場故事,個人成長經驗。

大週末的還是6點起床,起床的第一件事就是開啟電腦,因為昨天下班晚,回去看了會書就休息了,本來今天是可以有一個休息時間的,結果專案出了點小意外,還要去加班,你說心塞不心塞。

公眾號的文章都是中午時間整理,晚上再編輯釋出的,昨天時間太緊,就改成今天早上了。

今天我就像聊一個小知識點,執行緒同步。

廢話不多說,先說概念,小夥伴先想想你的理解。

java執行緒的同步有一個關鍵詞synchronize從英譯過來是 "同時發生"。但其真正的含義和字面意思截然相反。執行緒同步的真實意思,其實是“排隊”:幾個執行緒之間要排隊,一個一個對共享資源進行操作,而不是同時進行操作。


使用執行緒同步的目的:
是讓各個執行緒去排隊使用資源,而不是讓執行緒同時去使用資源

概念只是讓我們明白這個東西是幹什麼的,但是怎麼做,具體怎麼使用需要通過例項來說明。

對於執行緒同步我們生活中就有一個很好的例子就是買車票.

你看全國這麼多人買票,不同的方式是(車站,攜程,12306,代理視窗),車票肯定不是無限的,但是怎麼做到讓票賣出去,不會出現漏賣和空賣,怎麼做到車票同步的呢?

1, 不同步

為了對比我們先來看看 如果 不是同步賣票 會出現什麼情況?

public class ThreadSyn implements Runnable{
    //有5張票
    int ticked = 5;
    @Override
    //重寫run()方法
    public void run() {
        for(int i=ticked;i>0;i--) {
            System.out.println(Thread.currentThread().getName() + " sells " + i + " ticket");
        }
    }
    //main方法測試
    public static void main(String[] args) {
        //例項化Thread物件
        ThreadSyn tT = new ThreadSyn();
        Thread td1 = new Thread(tT,"火車站");
        Thread td2 = new Thread(tT,"攜程");
        Thread td3 = new Thread(tT,"代理商");
        Thread td4 = new Thread(tT,"12306");
        //啟動執行緒
        td1.start();
        td2.start();
        td3.start();
        td4.start();
    }
}

輸入結果:
火車站 sells 5 ticket
攜程 sells 5 ticket
攜程 sells 4 ticket
火車站 sells 4 ticket
火車站 sells 3 ticket
火車站 sells 2 ticket
火車站 sells 1 ticket
攜程 sells 3 ticket
攜程 sells 2 ticket
攜程 sells 1 ticket
代理商 sells 5 ticket
代理商 sells 4 ticket
代理商 sells 3 ticket
代理商 sells 2 ticket
代理商 sells 1 ticket
12306 sells 5 ticket
12306 sells 4 ticket

12306 sells 3 ticket
12306 sells 2 ticket
12306 sells 1 ticket

Process finished with exit code 0

結果優點崩潰,一共剩餘5張票了,但是四個不同的方式,每一個竟然都能買到5張,這是不是有點亂了。

所以就有了同步的概念,當A在買票的時候,B在等待,A買完以後 系統同步票數,直到C去買票的時候,發現沒有票了。

public class ThreadSyn implements Runnable{

    int ticket = 8;
    //擔任"鎖",鎖是什麼不重要,他只是一把鎖
    //要求,非空物件
    private String mutex = "";
    @Override
    //重寫run()方法
    public void run() {
        //while迴圈
        while (true) {
            synchronized (mutex) {
                if(ticket > 0) {
                    System.out.println(Thread.currentThread().getName()+ " sells " + ticket-- + " ticket.");
                }else {
                    break;
                }
            }
        }
    }
    //main方法測試
    public static void main(String[] args) {
        //例項化Thread物件
        ThreadSyn tT = new ThreadSyn();
        Thread td1 = new Thread(tT,"火車站");
        Thread td2 = new Thread(tT,"攜程");
        Thread td3 = new Thread(tT,"代理商");
        Thread td4 = new Thread(tT,"12306");
        //啟動執行緒
        td1.start();
        td2.start();
        td3.start();
        td4.start();
    }
}

攜程 sells 8 ticket.
攜程 sells 7 ticket.
攜程 sells 6 ticket.
攜程 sells 5 ticket.
攜程 sells 4 ticket.
攜程 sells 3 ticket.
攜程 sells 2 ticket.
攜程 sells 1 ticket.

Process finished with exit code 0

結果可以添加了同步後,只賣了現有8張票,買完為止。

本文 Github ( 碼雲Gitee同步) https://github.com/ProceduralZC/JavaDevGuide/tree/master/code/JavaTheead/ThreadSynchron 已收錄,歡迎 star。

我是【爾東雙月】一枚執著的職場程式設計師,微信搜尋【程式職場】關注我。別忘了三連啊,點贊、收藏、留言,隨意給,我不挑。
知乎號: 程式職場
注:如果文章有任何問題,歡迎毫不留情地指正。