黑馬程式員-----Java基礎之多線程

來源:互聯網
上載者:User

標籤:多線程

進程與線程

進程:就是進行中的程式。其實就是一個應用程式運行時的記憶體空間。

線程:線程就是進程當中的一個控制單元或執行路徑。進程負責空間的標示,而線程負責執行應用程式的執行順序。

當一個進程中出現多個線程是就是多線程。每個線程在棧中都有自己的執行空間、方法區、變數。

java VM啟動的時候會有一個進程java.exe。該進程中至少有一個線程負責java程式的執行,而且這個線程啟動並執行代碼存在於main方法中。該線程稱之為主線程。

線程的建立方法

建立線程中第一種方式:繼承Thread類

步驟:

    1.定義類繼承Thread類

    2.複寫Thread類中run方法

        目的:將自訂代碼儲存在run方法,讓線程運行。

    3.調用線程start方法

        該方法有兩個作用:啟動線程,調用run方法。

為什麼覆蓋run方法?

Thread類用於描述線程。該類定義了一個功能,用於儲存線程要啟動並執行代碼。該儲存功能就是run方法。

也就是說Thread類中run方法,用於儲存線程要啟動並執行代碼。

    線程都有自己的名稱:Thread-編號 該編號從0開始,。

    static Thread currentThread();擷取當前線程對象。

    getName()擷取線程名稱。

    設定線程名稱: setName()或者建構函式。

代碼執行個體:

class Demo extends Thread

{

    public void run()

    {

       for(int x=0; x<60; x++)

           System.out.println("demo run----"+x);

    }

}

class ThreadDemo

{

    public static void main(String[] args)

    {

       Demo d = new Demo();//建立好一個線程。

       d.start();//開啟線程並執行該線程的run方法。

       //d.run();//僅僅是對象調用方法。而線程建立了,並沒有運行。

       for(int x=0; x<60; x++)

           System.out.println("Hello World!--"+x);  

    }

}

第二種方式:實現Runable介面

步驟:

    1.定義類實現Runable介面

    2.覆蓋Runable介面中的run方法。

        將線程啟動並執行代碼儲存在run方法中。

    3.通過Thread類建立線程對象。

    4.將Runable介面的子類對象作為實際參數傳遞給Thread類的建構函式。Thread(Runable r)

    自訂的run方法所屬的對象是Runable介面的子類對象。所以要讓線程去運行指定對象的run方法。就必須明確該run方法所屬的對象。

    5.調用Thread類的start方法開啟線程(調用Runable介面子類中的run方法。)

售票執行個體:

class Ticket implements Runnable//extends Thread

{

    private  int tick = 100;

    public void run()

    {

       while(true)

       {

           if(tick>0)

           {

              System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);

           }

       }

    }

}

class  TicketDemo

{

    public static void main(String[] args)

    {

       Ticket t = new Ticket();

       Thread t1 = new Thread(t);//建立了一個線程;

       Thread t2 = new Thread(t);//建立了一個線程;

       Thread t3 = new Thread(t);//建立了一個線程;

       Thread t4 = new Thread(t);//建立了一個線程;

       t1.start();

       t2.start();

       t3.start();

       t4.start();

           }

}

兩種方式的區別:

繼承Thread:線程代碼存放Thread子類的run方法中。

實現Runable:線程代碼存放在介面的子類的run方法。

實現方式避免了單繼承的局限性,在定義線程時,建議使用實現方式

線程狀態

    1.被建立:等待啟動,調用start啟動。

    2.運行狀態:具有執行資格和執行權。

    3.臨時狀態(阻塞):有執行資格,但是沒有執行權。

    4.凍結狀態:遇到sleep(time)方法和wait()方法時,失去執行資格和執行權,sleep方法時間到或者調用notify()方法時,獲得執行資格,變為臨時狀態。

    5. 消忙狀態:stop()方法,或者run方法結束。

多安全執行緒問題:一個線程在運行多條語句、操作同一個資料的時候,其他線程參與進來。導致錯誤資料的產生。

解決辦法:只要讓共用資料在某一時間只由一個線程執行,在此過程中其他的不能執行。所以會用到同步 Sychronized(對象){需要被同步的代碼}。

   對象如同鎖,持有鎖的線程可以在同步中執行,沒有持有鎖的線程即使擷取CPU的執行權,也進不去,因為沒有擷取鎖

同步函數:用synchronized修飾函數即可。

    鎖是this。若同步函數被static修飾,所屬類.class。

同步的前提

    必須有兩個或兩個以上線程才需要同步

    多個線程必須用同一個鎖。

同步的好處是解決的安全執行緒問題,弊端是需要不斷的判斷鎖,消耗資源。

多線程間通訊和一些線程操作方法

線程間通訊其實就是多個線程在操作同一個資源,但是操作的動作不同 

需要使用的方法有:

wait();

notify();

notifyAll(); 

上面的方法都使用在同步中,因為要對持有監視器(鎖)的線程操作,所以要使用在同步中,因為只有同步才具有鎖 

為什麼這些操作線程的方法要定義在Object類中呢?

因為這些方法在操作同步中線程時,都必須要標識它們所操作線程持有的鎖,只有同一個鎖上的被等待線程,可以被同一個鎖上的notify喚醒,不可以對不同鎖中的線程進行喚醒,也就是說,等待和喚醒必須是同一個鎖,而鎖可以是任意對象,所以可以被任意對象調用的方法定義在Object類中。

同步中的死結問題

何時會出現死結?當同步中嵌套同步時會出現死結。 這時會出現一個線程持有a鎖要想執行下去要擷取b鎖,而另一個線程持有b鎖要想執行下去要擷取a鎖。這就成了兩個線程各自持有一個鎖,又要擷取對方的鎖,這時就出現了死結。程式會定在那執行不下去。

停止線程

只有一種,run方法結束。開啟多線程運行,運行代碼通常是迴圈結構。只要控制住迴圈,就可以讓run方法結束,也就是線程結束。

特殊情況:

當線程處於了凍結狀態。就不會讀取到標記。那麼線程就不會結束。當沒有指定的方式讓凍結的線程恢複到運行狀態時,這時需要對凍結進行清除。強制讓線程恢複到運行狀態中來。這樣就可以操作標記讓線程結束。Thread類提供該方法 interrupt();


本文出自 “點點滴滴” 部落格,請務必保留此出處http://arctictern.blog.51cto.com/10120640/1659840

黑馬程式員-----Java基礎之多線程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.