執行緒的【生命週期】和【執行緒的同步】(多視窗售票例子)

小白衝發表於2021-04-11

 

 JDK 中用Thread.State 類定義了執行緒的幾種狀態
要想實現多執行緒,必須在主執行緒中建立新的執行緒物件。Java語言使用Thread類
及其子類的物件來表示執行緒,在它的一個完整的生命週期中通常要經歷如下的 五
種狀態:


新建: 當一個Thread類或其子類的物件被宣告並建立時,新生的執行緒物件處於新建
狀態


就緒:處於新建狀態的執行緒被start()後,將進入執行緒佇列等待CPU時間片,此時它已
具備了執行的條件,只是沒分配到CPU資源


執行:當就緒的執行緒被排程並獲得CPU資源時,便進入執行狀態, run()方法定義了線
程的操作和功能


阻塞:在某種特殊情況下,被人為掛起或執行輸入輸出操作時,讓出 CPU 並臨時中
止自己的執行,進入阻塞狀態


死亡:執行緒完成了它的全部工作或執行緒被提前強制性地中止或出現異常導致結束

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

解決方法:

/**
* 例子:建立三個視窗賣票,總票數為100張.使用實現Runnable介面的方式
*
* 1.問題:賣票過程中,出現了重票、錯票 -->出現了執行緒的安全問題
* 2.問題出現的原因:當某個執行緒操作車票的過程中,尚未操作完成時,其他執行緒參與進來,也操作車票。
* 3.如何解決:當一個執行緒a在操作ticket的時候,其他執行緒不能參與進來。直到執行緒a操作完ticket時,其他
* 執行緒才可以開始操作ticket。這種情況即使執行緒a出現了阻塞,也不能被改變。
*
*
* 4.在Java中,我們通過同步機制,來解決執行緒的安全問題。
*
* 方式一:同步程式碼塊
*
* synchronized(同步監視器){
* //需要被同步的程式碼
*
* }
* 說明:1.操作共享資料的程式碼,即為需要被同步的程式碼。 -->不能包含程式碼多了,也不能包含程式碼少了。
* 2.共享資料:多個執行緒共同操作的變數。比如:ticket就是共享資料。
* 3.同步監視器,俗稱:鎖。任何一個類的物件,都可以充當鎖。
* 要求:多個執行緒必須要共用同一把鎖。
*
* 補充:在實現Runnable介面建立多執行緒的方式中,我們可以考慮使用this充當同步監視器。
* 方式二:同步方法。
* 如果操作共享資料的程式碼完整的宣告在一個方法中,我們不妨將此方法宣告同步的。
*
*
* 5.同步的方式,解決了執行緒的安全問題。---好處
* 操作同步程式碼時,只能有一個執行緒參與,其他執行緒等待。相當於是一個單執行緒的過程,效率低。 ---侷限性
*
* @author ch
* @create 2019-02-13 下午 4:47
*/
class Window1 implements Runnable{

    private int ticket = 100;
//    Object obj = new Object();
//    Dog dog = new Dog();
    @Override
    public void run() {
//        Object obj = new Object();
        while(true){
            synchronized (this){//此時的this:唯一的Window1的物件   //方式二:synchronized (dog) {

                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + ":賣票,票號為:" + ticket);


                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}


public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("視窗1");
        t2.setName("視窗2");
        t3.setName("視窗3");

        t1.start();
        t2.start();
        t3.start();
    }

}

 

相關文章