1. 程式人生 > >Java複習筆記之執行緒問題

Java複習筆記之執行緒問題

一、執行緒的基本問題

作業系統中可以獨立執行的程式叫程序,程序有多個執行單元,這些執行單元可以叫做執行緒。

一個程序至少包括一個執行緒,執行緒也叫輕量級程序。

同作業系統呼叫程序一樣,程序裡的多個執行緒看似同時執行。其實也是由CPU輪流執行的,只不過CPU執行速度很快,故而給人同時執行的錯覺。

建立執行緒有兩種方式

1.繼承Thread類 

class MyThread extends Thread{

     public void run(){……};//一定要寫的方法,必須這麼寫

//必須這麼寫的原因有三條

//1.如果改變public為protected等,然而父類中的run方法還是public。規則是子類不能比父類的級別低,更改的話就違反了這條

//2.如果新增引數,則變為普通方法,不會在呼叫start()方法後執行run()方法。

//3.只認void的返回值,否則編譯時就會報錯

}

建立執行緒物件時則使用 MyThread my = new MyThread();

my.start();//start()方法用於啟動新執行緒,系統會自動呼叫run()方法。

若要為程序重新命名則可以重寫MyThread的構造方法,比如

public MyThread(String string) {
        this.setName(string);
    }

呼叫時使用new MyThread("name1")就行了。

2.實現Runnable介面

class MyThread implements Runnable{

 public void run(){……};//Runnable中只有這一個方法,所以一定要實現

}

建立執行緒物件時,需要呼叫Thread()的建構函式才行

MyThread my = new MyThread();

Thread td = new Thread(my);

td.start();

簡化版1

Thread td = new Thread(new MyThread());

td.start()

;

簡化版2

new Thread(new MyTherad()).start();

Thread的構造方法中還可以傳入執行緒名比如new Thread(my,“執行緒名”)

兩種方法的對比。

Runnable 更適合多個執行緒處理一個資源的情況,把執行緒同程式程式碼、資料有效的分離,很好的體現了面向物件的設計思想。

Thread建立的不同執行緒擁有不同的資源。

Runnable 可以避免Java的單繼承帶來的侷限性。

獲取當前執行緒的名字可以通過Thread.currentThread().getName();

二、執行緒的同步問題

實現同步問題有兩個方法,同步程式碼塊和同步方法,關鍵字是synchronized

容易知道,同步程式碼塊的鎖是使用者自定義的任意物件。

那麼同步方法當然也有鎖,就是呼叫該方法的物件,也就是this指向的物件,可以用this獲取。因為物件對執行緒來說也具有唯一性,所以可以作為鎖。

如果同步的是靜態方法,不需要建立物件就可以呼叫,那麼靜態方法的鎖就是該方法所在類的class物件,可以用“類名.class”獲取。

同步解決了多個執行緒同時訪問共享資料的執行緒安全問題,即同一時間只能由一個執行緒訪問公共資源。

但是因為每次都要判斷鎖的狀態,所以非常消耗資源,效率低。

當兩個執行緒都需要使用對方的鎖,但又不釋放自己的鎖就會造成死鎖。

java虛擬機器沒有檢測,也沒有采用措施來處理死鎖情況,所以多執行緒程式設計是應該採取措施避免死鎖的出現。

一旦出現死鎖,整個程式即不會發生任何異常,也不會給出任何提示,只是所有執行緒都處於堵塞狀態。

三、其他注意的

1.解決執行緒之間的通訊問題的方法wait()、notify()、notifyAll()。

2.sleep()和wait()方法的區別?

sleep()方法讓出CPU但不會釋放同步鎖,等時間到了之後再執行當前執行緒

wait()在同步鎖內呼叫,釋放同步鎖,被喚醒後進入就緒狀態等待下一次獲得同步鎖

3.yield()和join()

yield()讓出控制權,進入就緒狀態使系統重新呼叫一次,不會阻塞程序。某個程序yield()之後,只有優先順序>=當前程序優先順序的才有可能被呼叫

當A執行緒中使用B.join()時,A將被阻塞,等B執行完時A才能繼續執行。

4.不同作業系統對執行緒優先順序的支援不一樣,不能很好的和Java中的執行緒優先順序一一對應,所以不能依賴優先順序。

5.對Java來說,只要還有一個前臺執行緒在執行,這個程序就不會結束,但只有後臺執行緒在執行,這個程序就會結束。

可以使用   執行緒.setDaemon(true),來使前臺執行緒轉換成後臺執行緒,而且必須在start()方法之前使用,否則報錯。

前後臺執行緒是相對的概念,新建立的執行緒預設都是前臺執行緒。

6.執行緒的5種狀態和轉換

.