更新時(shí)間:2021-03-17 來源:黑馬程序員 瀏覽量:
售票案例中,極有可能碰到“意外”情況,如一張票被打印多次,或者打印出的票號為0甚至負(fù)數(shù)。這些“意外”都是由多線程操作共享資源tickets所導(dǎo)致的線程安全問題,接下來對案例進(jìn)行修改,模擬四個(gè)窗口出售10張票,并在售票的代碼中每次售票時(shí)線程休眠100毫秒,如文件1所示。
文件1 Example11.java
// 定義SaleThread類實(shí)現(xiàn)Runnable接口 class SaleThread implements Runnable { private int tickets = 10; // 10張票 public void run() { while (true) { if (tickets > 0) { try { Thread.sleep(100); // 模擬售票耗時(shí)過程 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " 正在發(fā)售第 " + tickets-- + " 張票 "); } } } } public class Example11 { public static void main(String[] args) { SaleThread saleThread = new SaleThread(); // 創(chuàng)建并開啟四個(gè)線程,模擬4個(gè)售票窗口 new Thread(saleThread, "窗口1").start(); new Thread(saleThread, "窗口2").start(); new Thread(saleThread, "窗口3").start(); new Thread(saleThread, "窗口4").start(); } }
運(yùn)行結(jié)果如圖1所示。
圖1 運(yùn)行結(jié)果
圖1中,最后幾行打印售出的票為0和負(fù)數(shù),這種現(xiàn)象是不應(yīng)該出現(xiàn)的,因?yàn)樵谑燮背绦蛑凶隽伺袛嘀挥挟?dāng)票號大于0時(shí)才會(huì)進(jìn)行售票。運(yùn)行結(jié)果中之所以出現(xiàn)了負(fù)數(shù)的票號是因?yàn)槎嗑€程在售票時(shí)出現(xiàn)了安全問題。
在售票程序的while循環(huán)中添加了sleep()方法,這樣就模擬了售票過程中線程的延遲。由于線程有延遲,當(dāng)票號減為1時(shí),假設(shè)窗口2線程此時(shí)出售1號票,對票號進(jìn)行判斷后,進(jìn)入while循環(huán),在售票之前通過sleep()方法模擬售票時(shí)耗時(shí)操作,這時(shí)窗口1線程會(huì)進(jìn)行售票,由于此時(shí)票號仍為1,因此窗口1線程也會(huì)進(jìn)入循環(huán),同理,四個(gè)線程都會(huì)進(jìn)入while循環(huán),休眠結(jié)束后,四個(gè)線程都會(huì)進(jìn)行售票,這樣就相當(dāng)于將票號減了四次,結(jié)果中出現(xiàn)了1、0、-1、-2這樣的票號。
猜你喜歡:
2021年黑馬Java學(xué)習(xí)線路圖發(fā)布【含免費(fèi)自學(xué)視頻】