Java基礎 多執行緒

2021-07-03 16:23:22 字數 4533 閱讀 1202

多執行緒的概念,如何在程式中建立多執行緒(thread、runnable),執行緒安全問題,執行緒的同步,執行緒之間的通訊、死鎖。

一、 建立執行緒和啟動執行緒。

為什麼要覆蓋run方法:thread類用於描述執行緒。

該類就定義了乙個功能。用於儲存執行緒要執行的**。該儲存功能就是run方法。

也就是說thread類中的run方法。用於儲存執行緒要執行的**。

建立執行緒的兩種方法中,實現ruunable介面可以避免單繼承的侷限性。

啟動執行緒d1.run(); t1.start();run和start的區別:d1.run();就開始執行run方法中的**了。

start方法是:啟動執行緒,呼叫run方法。

二  執行緒的安全機制

執行緒安全問題都是由全域性變數及靜態變數引起的。當乙個執行緒在執行時,

另乙個執行緒進來並改變了當前執行緒運算需要用到的變數的值,這就會導致當前執行緒計算出錯,

這就是執行緒的不安全。

為了提高多執行緒安全性,解決方法有同步**塊和同步函式。

同步的前提:

1.必須要有兩個或者兩個以上的執行緒。

2.必須是多個執行緒使用同乙個鎖。

利弊:好處:解決了執行緒安全問題。

弊端:多個執行緒需要判斷鎖,較為消耗資源。

**例項:

package thread;

/** * @author administrator

*建立新執行執行緒有兩種方法。一種方法是將類宣告為 thread 的子類。

* 該子類應重寫 thread 類的 run 方法。

* *另一種方法是宣告實現 runnable 介面的類。該類然後實現 run 方法。

* **將實現了runnable介面的子類物件作為實際引數傳遞給thread類中的建構函式。

*/public class threadbandtest }/*

* 同步的兩種表達方式

1,同步**塊

2,同步函式

* */

//建立銀行類

class bank catch (exception e)

system.out.println("sum= "+sum);

}*///同步**塊實現執行緒的**共享

object obj = new object();

public void add(int n) catch (exception e)

system.out.println("sum = "+sum);

} } }

//繼承thread

class demo extends thread

}//建立儲戶類 實現runnable介面

class cus implements runnable }}

三  執行緒之間的通訊

執行緒之間通訊:其實就是多個執行緒在操作同乙個資源。但是操作的動作不同。用到的方法如下:

wait();當前執行緒處於等待狀態,直到有notify將其喚醒。

notify();喚醒乙個執行緒池中持有同樣鎖的等待執行緒,通常喚醒第乙個被等待的執行緒。

notifyall();喚醒執行緒池中所有的等待

這三個方法都使用在同步中,因為要對持有監視器(鎖)的執行緒操作。所以要使用在同步中,因為只有同步才具有鎖

為什麼這些操作執行緒的方法要定義在object中呢?

因為這些方法在操作同步中線程時,都必須要標識他們所操作執行緒持有的鎖只有同乙個鎖上的被等待執行緒,

可以被同乙個鎖上的notify喚醒。不可以對不同鎖中的執行緒進行喚醒。

也就是說等待跟喚醒必須是同一把鎖

而鎖可以是任意物件,所以可以被任意物件呼叫的方法定義在object類中

示例**:

演示兩個執行緒操作同乙個資源,但是動作不同,將兩個動作的**塊都進行同步,並且使用同一把鎖,

但是存在動作一或者動作二一直持有執行權和執行資格,為了實現存入和輸出交替進行,加入了wait()和notify方法,

輸入和輸出通過判斷標誌flag的真假,交替進行。

但是存在同步巢狀的情況,這時同步所用的鎖不同,這樣就導致在執行wait和notify的時候具體等待或者喚醒哪個執行緒

不明確,所以要標識鎖,如r.wait();   r.notify();  喚醒的是持有r這把鎖的同步**塊中的執行緒,

1.動作一,存入資訊

synchronized(r)

catch(exception e){}

if(x==0)

else

x=(x+1)%2;

r.flag=true;//存完以後置為真,此時存入執行緒判斷為真,執行等待。

r.notify();//喚醒輸出資訊執行緒

}

2.動作二,輸出資訊。

synchronized(r)

catch(exception e){}

system.out.println(r.name+"****"+r.***);

r.flag=false;//列印一次將標誌置為假,輸出執行緒再次判斷非假為真,等待被喚醒。

r.notify();//喚醒存入執行緒

}

注意:對於非靜態同步函式來說。它的鎖是this,this.wait();  this.notify();

public synchronized void set(string name,string ***)

catch(exception e){}

this.name=name;

this.***=***;

flag=true;

this.notify();

}

執行緒之間通訊示例**:

class res  //定義乙個共同操作的資源,即共享資料

catch(exception e){}

this.name=name;

this.***=***;

flag=true;

this.notify();

} public synchronized void out()

catch(exception e){}

system.out.println(name+"****"+***);

flag=false;

this.notify(); }}

class input implements runnable //輸入方法

public void run() }

}class output implements runnable//輸出方法

public void run() }

}class inputoutputdemo2

}

四 、執行緒停止

如何停止執行緒?

* 讓run方法結束,即控制迴圈結束,但是存在特殊情況:當執行緒處於凍結狀態,就不會讀到結束標誌,執行緒就不會結束。

*這時就要對凍結狀態進行清除,讓執行緒恢復到執行狀態,這樣就可以操作標記讓執行緒結束。

*thread類中提供了該 方法:interrupt();方法。

**例項:

class stopthreaddemo 

system.out.println(thread.currentthread().getname()+"****main****run"+num);

} }}class stopthread implements runnable catch (interruptedexception e)

system.out.println(thread.currentthread().getname()+"******run");

} }public void changeflag()

}

五 、多執行緒中的單例設計模式

懶漢式  多執行緒訪問時出現安全問題  採用同步函式效率低下(加的鎖是該類所屬的位元組碼檔案物件 類名.class)

**例項:

class single

public static single getinstance()

}}}

六 、死鎖

造成死鎖的原因:同步中巢狀同步,而鎖不同。我們在程式設計時要盡量避免死鎖這種情況的出現。

示例**:

package thread;

public class deadlockdemo

}class test implements runnable

public void run()

}} else

}} } }

class mylock

Java多執行緒基礎

thread.currentthread 與this的區別 thread t1 new thread target 在上述 中,thread.currentthread 指的是t1執行緒,this指的是target執行緒。可重入鎖 setdaemon boolean on 將當前執行緒設定為守護執行...

java基礎複習 多執行緒

第一節 兩種建立方法 1繼承thread類,並複寫run方法 2實現runnable介面,並複寫run方法 3兩種方式的特點和優缺點,以及應用。賣票程式中,使用1方法建立的執行緒,每建立乙個執行緒,都有100張票。而我們想要的多個執行緒共同操作這100張票,這時就要使用第二種方法。第二節 執行緒的執...

Java基礎之多執行緒

實現介面runnable 實現介面callable 結合執行緒池 實現callable介面或者runnable介面 呼叫如下方法即可 結束任務 執行緒池方式 初始化執行緒池 executorservice pool executors.newfixedthreadpool 2 可以執行runnabl...