亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

java多線程詳細總結

2019-11-26 15:57:04
字體:
來源:轉載
供稿:網友

一、Thread.start()與Thread.run()的區別

通過調用Thread類的start()方法來啟動一個線程,這時此線程是處于就緒狀態,并沒有運行。然后通過此Thread類調用方法run()來完成其運行操作的,這里方法run()稱為線程體,它包含了要執行的這個線程的內容,Run方法運行結束,此線程終止,而CPU再運行其它線程。

而如果直接用Run方法,這只是調用一個方法而已,程序中依然只有“主線程”這一個線程,并沒有開辟新線程,其程序執行路徑還是只有一條,這樣就沒有達到寫線程的目的。

測試代碼如下

復制代碼 代碼如下:

public class MyThread implements Runnable {
public void run() {
System.err.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread t1 = new Thread(thread, "Thread-1");
Thread t2 = new Thread(thread, "Thread-2");
t1.run();
t2.run();
}
}

輸出結果為

>>當前進程為:main

>>當前進程為:main

改為用start方法:

復制代碼 代碼如下:

package thread;
public class MyThread implements Runnable {
public void run() {
System.err.println(">>當前進程為:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread t1 = new Thread(thread, "Thread-1");
Thread t2 = new Thread(thread, "Thread-2");
t1.start();
t2.start();
}
}

結果為:

>>當前進程為:Thread-1

>>當前進程為:Thread-2

二、ThreadLocal類詳解

ThreadLocal很容易讓人望文生義,想當然地認為是一個“本地線程”。其實,ThreadLocal并不是一個Thread,而是Thread的局部變量,也許把它命名為ThreadLocalVariable更容易讓人理解一些。當使用ThreadLocal維護變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。

下面是線程局部變量(ThreadLocal variables)的關鍵點:

一個線程局部變量(ThreadLocal variables)為每個線程方便地提供了一個單獨的變量。在多個線程操作該變量時候能夠互不影響,因為每個線程操作的實際上是改變量的副本。ThreadLocal實例通常作為靜態的私有的(private static)字段出現在一個類中,這個類用來關聯線程。當多個線程訪問ThreadLocal實例時,每個線程維護ThreadLocal提供的獨立的變量副本。

下面是測試代碼,用于測試:作用于一個對象上面的三個線程來操作同一個ThreadLoacl對象(integer 類型),看是否會出現臟讀等現象:

復制代碼 代碼如下:

public class Test implements Runnable {
private static ThreadLocal<Integer> num = new ThreadLocal<Integer>();
public void run() {
num.set(0);
for (int i = 0; i < 3; i++) {
num.set(num.get() + 1);
System.out.println(Thread.currentThread().getName() + ":num="
+ num.get());
}
}
public static void main(String[] args) {
Test test = new Test();
Thread t1 = new Thread(test, "Thread-1");
Thread t2 = new Thread(test, "Thread-2");
Thread t3 = new Thread(test, "Thread-3");
t1.start();
t2.start();
t3.start();
}
}

運行結果如下:

Thread-3:num=1
Thread-2:num=1
Thread-1:num=1
Thread-2:num=2
Thread-3:num=2
Thread-2:num=3
Thread-1:num=2
Thread-1:num=3
Thread-3:num=3

從上面可以看出,完全沒有出現臟讀等的現象,因此ThreadLocal線程安全。

常用的使用:當DAO類作為一個單例類時,數據庫鏈接(connection)被每一個線程獨立的維護,互不影響。

可以用來控制session的創建和使用,如下ThreadLocal<Session> session = new ThreadLocal<Session>();

ThreadLoacal與同步機制的比較:

1、在同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。

2、而ThreadLocal則從另一個角度來解決多線程的并發訪問。ThreadLocal會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。

3、概括起來說,對于多線程資源共享的問題,同步機制采用了“以時間換空間”的方式,而ThreadLocal采用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。

三、InvalidMonitorStateException異常

調用wait()/notify()/notifyAll()中的任何一個方法時,如果當前線程沒有獲得該對象的鎖,那么就會拋出IllegalMonitorStateException的異常(也就是說程序在沒有執行對象的任何同步塊或者同步方法時,仍然嘗試調用wait()/notify()/notifyAll()時)。由于該異常是RuntimeExcpetion的子類,所以該異常不一定要捕獲(盡管你可以捕獲只要你愿意).作為RuntimeException,此類異常不會在wait(),notify(),notifyAll()的方法簽名提及。

如下代碼,劃線的部分會發生該異常,因為沒有對該對象執行同步操作。

復制代碼 代碼如下:

public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Method 1 called");
Thread.sleep(1000);
System.out.println("Method 1 done");
}
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println("Method 2 called");
Thread.sleep(1000);
System.err.println("Method 2 done");
}
public void run() {
System.out.println("Running " + Thread.currentThread().getName());
try {
if (Thread.currentThread().getName().equals("Thread-1")) {
this.wait(1000);
method1();
} else {
method2();
notifyAll();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, "Thread-1");
Thread t2 = new Thread(c, "Thread-2");
t1.start();
t2.start();
}
}

改為一下代碼,劃線部分:
復制代碼 代碼如下:

public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Method 1 called");
Thread.sleep(1000);
System.out.println("Method 1 done");
}
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println("Method 2 called");
Thread.sleep(1000);
System.err.println("Method 2 done");
}
public void run() {
System.out.println("Running " + Thread.currentThread().getName());
try {
if (Thread.currentThread().getName().equals("Thread-1")) {
synchronized(this){
this.wait(1000);
}
method1();
} else {
method2();
synchronized (this) {
notifyAll();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, "Thread-1");
Thread t2 = new Thread(c, "Thread-2");
t1.start();
t2.start();
}
}

四、sleep()和wait()和suspend()的區別

區別一:

sleep是Thread類的方法,是線程用來控制自身流程的,比如有一個要報時的線程,每一秒中打印出一個時間,那么我就需要在print方法前面加上一個sleep讓自己每隔一秒執行一次。就像個鬧鐘一樣。 sleep() 指示當前線程暫停執行指定時間,把執行機會讓給其他線程,但是監控狀態依然保持,到時后會自動恢復。調用sleep不會釋放對象鎖。

wait是Object類的方法,用來線程間的通信,這個方法會使當前擁有該對象鎖的線程等待,直到其他線程調用notify方法時再醒來,不過你也可以給它指定一個時間,自動醒來。這個方法主要是用在不同線程之間的調度。對象調用wait()方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。

區別二 :
 
調用wait方法會釋放當前線程的鎖,其實線程間的通信是靠對象來管理的,所有操作一個對象的線程是這個對象通過自己的wait方法來管理的。就好像這個對象是電視機,三個人是三個線程,那么電視機的遙控器就是這個鎖,假如現在A拿著遙控器,電視機調用wait方法,那么A就交出自己的遙控器,由jVM虛擬機調度,遙控器該交給誰。

調用sleep方法不會釋放鎖,因為sleep()是一個線程用于管理自己的方法,不涉及線程通信。還是上面的例子,如果A拿遙控器的期間,他可以用自己的sleep每隔十分鐘調一次臺,而在他調臺休息的十分鐘期間,遙控器還在他的手上,其他人無法獲得遙控器。

suspend() 方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖。此時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖

在以下情況下,持有鎖的線程會釋放鎖:

1. 執行完同步代碼塊。

2. 在執行同步代碼塊的過程中,遇到異常而導致線程終止。

3. 在執行同步代碼塊的過程中,執行了鎖所屬對象的wait()方法,這個線程會釋放鎖,進行對象的等待池。

在以下情況下,線程雖然停止執行,但是線程不會釋放鎖:

1. 在執行同步代碼塊的過程中,執行了Thread.sleep()方法,當前線程放棄CPU,開始睡眠,在睡眠中不會釋放鎖。

2. 在執行同步代碼塊的過程中,執行了Thread.yield()方法,當前線程放棄CPU,但不會釋放鎖。

3. 在執行同步代碼塊的過程中,其他線程執行了當前對象的suspend()方法,當前線程被暫停,但不會釋放鎖。

五、在靜態方法上使用同步

JAVA只識別兩種類型的鎖:對象鎖和類鎖。

同步靜態方法時會獲取該類的"Class”對象,所以當一個線程進入同步的靜態方法中時,線程監視器獲取類本身的鎖,對整個類加鎖,其它線程不能進入這個類的任何靜態同步方法。它不像實例方法,因為多個線程可以同時訪問不同實例同步實例方法。測試代碼如下:

復制代碼 代碼如下:

public class Common implements Runnable {
public synchronized static void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Method 1 called");
Thread.sleep(1000);
System.out.println("Method 1 done");
}
public synchronized static void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println("Method 2 called");
Thread.sleep(1000);
System.err.println("Method 2 done");
}
public void run() {
System.out.println("Running " + Thread.currentThread().getName());
try {
if (Thread.currentThread().getName().equals("Thread-1")) {
method1();
} else {
method2();
// Thread.currentThread().notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
//以下代碼創建了不同的對象上的不同線程,用來測試對于同一個類,會不會有鎖
Common c1 = new Common();
Common c2 = new Common();
Thread t1 = new Thread(c1, "Thread-1");
Thread t2 = new Thread(c2, "Thread-2");
t1.start();
t2.start();
}
}

執行結果如下:
Running Thread-2
Running Thread-1
Method 2 called
Method 2 done
Method 1 called
Method 1 done

六、在一個對象上兩個線程可以在同一時間分別調用兩個不同的同步實例方法嗎?

不能,因為一個對象已經同步了實例方法,線程獲取了對象的對象鎖。所以只有執行完該方法釋放對象鎖后才能執行其它同步方法。測試代碼如下:

復制代碼 代碼如下:

public class Common implements Runnable {
public synchronized void method1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Method 1 called");
Thread.sleep(1000);
System.out.println("Method 1 done");
}
public synchronized void method2() throws InterruptedException {
Thread.sleep(1000);
System.err.println("Method 2 called");
Thread.sleep(1000);
System.err.println("Method 2 done");
}
public void run() {
System.out.println("Running " + Thread.currentThread().getName());
try {
if (Thread.currentThread().getName().equals("Thread-1")) {
method1();
} else {
method2();
// Thread.currentThread().notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
Common c = new Common();
Thread t1 = new Thread(c, "Thread-1");
Thread t2 = new Thread(c, "Thread-2");
t1.start();
t2.start();
//以下代碼作為對比,創建不同的對象,則就不會受對象鎖的干擾了
//Common c1 = new Common();
//Common c2 = new Common();
//c1.start();
//c2.start();
}
}

執行結果如下:
Running Thread-1
Running Thread-2
Method 1 called
Method 1 done
Method 2 called
Method 2 done

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品视频久久久久久| 97在线看免费观看视频在线观看| 欧美在线视频播放| 中文字幕亚洲字幕| 国产日韩视频在线观看| 欧美视频一区二区三区…| 色无极亚洲影院| 91av在线影院| 国产精品 欧美在线| xxx一区二区| 精品久久久久久久久久久| 国产一区二区成人| 欧美做受高潮1| 日韩免费在线播放| 中文字幕在线看视频国产欧美在线看完整| 国产欧美最新羞羞视频在线观看| 91av在线不卡| 国产精品专区一| 国语自产精品视频在免费| 久久av中文字幕| 亚洲精品福利视频| 亚洲18私人小影院| 亚洲欧美日韩第一区| 亚洲成人久久一区| 欧美视频精品一区| 亚洲伊人成综合成人网| 日韩精品在线免费观看| 成人乱人伦精品视频在线观看| 精品一区二区三区四区在线| 最新的欧美黄色| 久久久久久久久久久成人| 大量国产精品视频| 欧美黑人性生活视频| 狠狠色狠色综合曰曰| 国产91在线高潮白浆在线观看| 国产欧美精品xxxx另类| 欧美性生交xxxxx久久久| 欧美裸身视频免费观看| 国产精品国语对白| 97超级碰碰人国产在线观看| 国产视频久久久| 久久免费精品日本久久中文字幕| 国产成人avxxxxx在线看| 久久久久久久色| 久久久久免费精品国产| 欧美性猛交xxxxx免费看| 久久精品中文字幕免费mv| 一个人看的www久久| 欧美重口另类videos人妖| 欧美富婆性猛交| 国产精品三级网站| 91精品国产高清自在线| 搡老女人一区二区三区视频tv| 九九热这里只有精品6| 96精品久久久久中文字幕| 国产精品91在线观看| 国产91露脸中文字幕在线| 国产精品亚洲自拍| 中文字幕亚洲二区| 国产一区二区三区在线看| 国产精品扒开腿做爽爽爽男男| 国产精品稀缺呦系列在线| 正在播放欧美一区| 欧美日韩国产999| 欧美孕妇与黑人孕交| 日韩黄在线观看| 欧美日韩裸体免费视频| 亚洲片在线资源| 日韩精品欧美激情| 国产精品色婷婷视频| 国产精品久久久久福利| yellow中文字幕久久| 欧美成人精品一区| 亚洲免费视频在线观看| 欧美日韩激情小视频| 欧美精品一区二区三区国产精品| 欧美激情va永久在线播放| 国产精品男女猛烈高潮激情| 在线播放国产一区二区三区| 亚洲3p在线观看| 全亚洲最色的网站在线观看| 91探花福利精品国产自产在线| 国内揄拍国内精品少妇国语| 日韩在线免费视频| 色婷婷综合久久久久| 久久久久国产精品免费网站| 欧美在线一区二区三区四| 精品久久久久久久久久久久久| 日韩av中文字幕在线免费观看| 国产91成人在在线播放| 欧美激情xxxxx| 亚洲r级在线观看| 日韩av在线免费观看| 91av成人在线| 欧美孕妇毛茸茸xxxx| 亚洲精品电影久久久| 亚洲精品有码在线| www.国产精品一二区| 久久久久久久久久久久av| 97人人做人人爱| 91人人爽人人爽人人精88v| 日韩国产欧美精品一区二区三区| 97久久伊人激情网| 国产九九精品视频| 精品一区二区三区四区在线| 国产成人免费av| 成人日韩av在线| 日本精品在线视频| 国产精品欧美一区二区三区奶水| 亚洲国产天堂久久综合网| 自拍亚洲一区欧美另类| www.99久久热国产日韩欧美.com| 日韩在线观看网站| 国产成人鲁鲁免费视频a| 亚州成人av在线| 日韩最新免费不卡| 中文字幕亚洲一区二区三区五十路| 韩曰欧美视频免费观看| 国产日韩欧美中文| 久久免费观看视频| 92版电视剧仙鹤神针在线观看| www.久久撸.com| 日韩美女av在线免费观看| 久久久久久久久久国产| 久久综合五月天| 欧美日韩精品国产| 成人激情在线播放| 亚洲色图国产精品| 一个色综合导航| 91在线看www| 国产精品国模在线| 一本久久综合亚洲鲁鲁| 日韩视频免费在线| 国产成人精品视频在线观看| 亚洲精品网址在线观看| 亚洲国产成人精品久久久国产成人一区| 国产成人精品综合久久久| 热久久美女精品天天吊色| 日韩欧美在线视频日韩欧美在线视频| 成人h猎奇视频网站| 亚洲欧美精品伊人久久| 在线日韩日本国产亚洲| 欧美一区二粉嫩精品国产一线天| 国产成人精品电影久久久| 日韩av色在线| 成人国产精品日本在线| 国产脚交av在线一区二区| 精品久久久久久亚洲国产300| 精品久久久久久久久久| wwwwwwww亚洲| 亚洲人成网7777777国产| 欧美性xxxx极品高清hd直播| 一个人www欧美| 俺去啦;欧美日韩| 亚洲精品一区中文字幕乱码| 懂色av中文一区二区三区天美| 国模精品视频一区二区| 色视频www在线播放国产成人| 国产欧美一区二区三区久久| 欧美—级高清免费播放| 国内精品久久久久久久久| 亚洲欧美国产一本综合首页| 国产日韩欧美在线播放| 欧美在线日韩在线|