日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

【Java基础总结】多线程

發(fā)布時(shí)間:2023/11/29 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java基础总结】多线程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?1. 實(shí)現(xiàn)多線程的兩種方式

1 //第一種:繼承Thread類,重寫run()方法 2 class ThreadTest1 extends Thread{ 3 public void run(){ 4 String threadName = Thread.currentThread().getName(); 5 for(int i=0;i<10;i++){ 6 System.out.println("ThreadTest1 "+threadName+" running ... "+i); 7 } 8 } 9 } 10 11 //第二種:實(shí)現(xiàn)Runnable接口,重寫run()方法 12 class ThreadTest2 implements Runnable{ 13 public void run(){ 14 String threadName = Thread.currentThread().getName(); 15 for(int i=0;i<10;i++){ 16 System.out.println("ThreadTest2 "+threadName+" running ... "+i); 17 } 18 } 19 }

實(shí)現(xiàn)方式不同,使用方式也不同

public class Demo1{ public static void main(String[] args){ThreadTest1 t1 = new ThreadTest1();ThreadTest1 t2 = new ThreadTest1();Thread t3 = new Thread(new ThreadTest2());Thread t4 = new Thread(new ThreadTest2());t1.start();t2.start();t3.start();t4.start();} }

運(yùn)行結(jié)果大致如下:

ThreadTest1 Thread-0 running ... 0 ThreadTest2 Thread-3 running ... 0 ThreadTest2 Thread-2 running ... 0 ThreadTest1 Thread-1 running ... 0 ThreadTest2 Thread-2 running ... 1 ThreadTest2 Thread-3 running ... 1 ThreadTest1 Thread-0 running ... 1 ThreadTest2 Thread-3 running ... 2 ThreadTest2 Thread-2 running ... 2 ThreadTest1 Thread-1 running ... 1 ThreadTest2 Thread-2 running ... 3 ThreadTest2 Thread-3 running ... 3 ThreadTest1 Thread-0 running ... 2 ThreadTest2 Thread-3 running ... 4 ThreadTest2 Thread-2 running ... 4 ThreadTest1 Thread-1 running ... 2 ThreadTest2 Thread-2 running ... 5 ThreadTest2 Thread-3 running ... 5 ThreadTest1 Thread-0 running ... 3 ThreadTest2 Thread-3 running ... 6 ThreadTest2 Thread-2 running ... 6 ThreadTest1 Thread-1 running ... 3 ThreadTest2 Thread-2 running ... 7 ThreadTest2 Thread-3 running ... 7 ThreadTest2 Thread-3 running ... 8 ThreadTest2 Thread-3 running ... 9 ThreadTest1 Thread-0 running ... 4 ThreadTest1 Thread-0 running ... 5 ThreadTest2 Thread-2 running ... 8 ThreadTest2 Thread-2 running ... 9 ThreadTest1 Thread-1 running ... 4 ThreadTest1 Thread-0 running ... 6 ThreadTest1 Thread-0 running ... 7 ThreadTest1 Thread-0 running ... 8 ThreadTest1 Thread-1 running ... 5 ThreadTest1 Thread-0 running ... 9 ThreadTest1 Thread-1 running ... 6 ThreadTest1 Thread-1 running ... 7 ThreadTest1 Thread-1 running ... 8 ThreadTest1 Thread-1 running ... 9 View Code

?

2. 線程共享資源

建議使用?實(shí)現(xiàn)Runnable接口,重寫run方法?的方式來實(shí)現(xiàn)多線程,它有如下優(yōu)點(diǎn):

1. 線程和代碼分離,多線程間可以共享資源

2. 避免了單繼承帶來的局限性

3.?多線程之間可以共享資源

tip

Thread.currentThread().getName() 獲得當(dāng)前線程的名稱 threadObj.setName() 設(shè)置線程名稱

?

案例:售票

class ThreadTest4 implements Runnable{private int ticket=20;public void run(){String threadName = Thread.currentThread().getName();while(ticket>0){System.out.println("ThreadTest4 "+threadName+" 售出 "+ticket+" 號(hào)票");ticket--;}} }

使用情況1:

(new Thread(new ThreadTest4(), "窗口a")).start();(new Thread(new ThreadTest4(), "窗口b")).start();(new Thread(new ThreadTest4(), "窗口c")).start();(new Thread(new ThreadTest4(), "窗口d")).start();

運(yùn)行情況說明A、B、C、D四個(gè)窗口也沒用共享count這個(gè)資源

主線程名稱:main ThreadTest4 窗口a 售出 20 號(hào)票 ThreadTest4 窗口a 售出 19 號(hào)票 ThreadTest4 窗口b 售出 20 號(hào)票 ThreadTest4 窗口b 售出 19 號(hào)票 ThreadTest4 窗口b 售出 18 號(hào)票 ThreadTest4 窗口b 售出 17 號(hào)票 ThreadTest4 窗口b 售出 16 號(hào)票 ThreadTest4 窗口b 售出 15 號(hào)票 ThreadTest4 窗口a 售出 18 號(hào)票 ThreadTest4 窗口b 售出 14 號(hào)票 ThreadTest4 窗口d 售出 20 號(hào)票 ThreadTest4 窗口c 售出 20 號(hào)票 ThreadTest4 窗口d 售出 19 號(hào)票 ThreadTest4 窗口b 售出 13 號(hào)票 ThreadTest4 窗口a 售出 17 號(hào)票 ThreadTest4 窗口b 售出 12 號(hào)票 ThreadTest4 窗口d 售出 18 號(hào)票 ThreadTest4 窗口c 售出 19 號(hào)票 ThreadTest4 窗口d 售出 17 號(hào)票 ThreadTest4 窗口b 售出 11 號(hào)票 ThreadTest4 窗口a 售出 16 號(hào)票 ThreadTest4 窗口b 售出 10 號(hào)票 ThreadTest4 窗口d 售出 16 號(hào)票 ThreadTest4 窗口c 售出 18 號(hào)票 ThreadTest4 窗口d 售出 15 號(hào)票 ThreadTest4 窗口b 售出 9 號(hào)票 ThreadTest4 窗口a 售出 15 號(hào)票 ThreadTest4 窗口b 售出 8 號(hào)票 ThreadTest4 窗口d 售出 14 號(hào)票 ThreadTest4 窗口c 售出 17 號(hào)票 ThreadTest4 窗口d 售出 13 號(hào)票 ThreadTest4 窗口b 售出 7 號(hào)票 ThreadTest4 窗口a 售出 14 號(hào)票 ThreadTest4 窗口b 售出 6 號(hào)票 ThreadTest4 窗口d 售出 12 號(hào)票 ThreadTest4 窗口c 售出 16 號(hào)票 ThreadTest4 窗口d 售出 11 號(hào)票 ThreadTest4 窗口b 售出 5 號(hào)票 ThreadTest4 窗口a 售出 13 號(hào)票 ThreadTest4 窗口b 售出 4 號(hào)票 ThreadTest4 窗口d 售出 10 號(hào)票 ThreadTest4 窗口c 售出 15 號(hào)票 ThreadTest4 窗口d 售出 9 號(hào)票 ThreadTest4 窗口b 售出 3 號(hào)票 ThreadTest4 窗口a 售出 12 號(hào)票 ThreadTest4 窗口b 售出 2 號(hào)票 ThreadTest4 窗口d 售出 8 號(hào)票 ThreadTest4 窗口c 售出 14 號(hào)票 ThreadTest4 窗口d 售出 7 號(hào)票 ThreadTest4 窗口b 售出 1 號(hào)票 ThreadTest4 窗口a 售出 11 號(hào)票 ThreadTest4 窗口a 售出 10 號(hào)票 ThreadTest4 窗口d 售出 6 號(hào)票 ThreadTest4 窗口c 售出 13 號(hào)票 ThreadTest4 窗口d 售出 5 號(hào)票 ThreadTest4 窗口a 售出 9 號(hào)票 ThreadTest4 窗口d 售出 4 號(hào)票 ThreadTest4 窗口c 售出 12 號(hào)票 ThreadTest4 窗口d 售出 3 號(hào)票 ThreadTest4 窗口a 售出 8 號(hào)票 ThreadTest4 窗口d 售出 2 號(hào)票 ThreadTest4 窗口c 售出 11 號(hào)票 ThreadTest4 窗口d 售出 1 號(hào)票 ThreadTest4 窗口a 售出 7 號(hào)票 ThreadTest4 窗口c 售出 10 號(hào)票 ThreadTest4 窗口a 售出 6 號(hào)票 ThreadTest4 窗口a 售出 5 號(hào)票 ThreadTest4 窗口a 售出 4 號(hào)票 ThreadTest4 窗口a 售出 3 號(hào)票 ThreadTest4 窗口a 售出 2 號(hào)票 ThreadTest4 窗口a 售出 1 號(hào)票 ThreadTest4 窗口c 售出 9 號(hào)票 ThreadTest4 窗口c 售出 8 號(hào)票 ThreadTest4 窗口c 售出 7 號(hào)票 ThreadTest4 窗口c 售出 6 號(hào)票 ThreadTest4 窗口c 售出 5 號(hào)票 ThreadTest4 窗口c 售出 4 號(hào)票 ThreadTest4 窗口c 售出 3 號(hào)票 ThreadTest4 窗口c 售出 2 號(hào)票 ThreadTest4 窗口c 售出 1 號(hào)票 View Code

使用情況2:

ThreadTest4 t2 = new ThreadTest4();(new Thread(t2,"窗口1")).start();(new Thread(t2,"窗口2")).start();(new Thread(t2,"窗口3")).start();(new Thread(t2,"窗口4")).start();

運(yùn)行情況說明A、B、C、D四個(gè)窗口共享count這個(gè)資源(但發(fā)生了訪問沖突)

主線程名稱:main ThreadTest4 窗口1 售出 20 號(hào)票 ThreadTest4 窗口2 售出 20 號(hào)票 ThreadTest4 窗口2 售出 19 號(hào)票 ThreadTest4 窗口2 售出 18 號(hào)票 ThreadTest4 窗口2 售出 17 號(hào)票 ThreadTest4 窗口2 售出 16 號(hào)票 ThreadTest4 窗口2 售出 15 號(hào)票 ThreadTest4 窗口2 售出 14 號(hào)票 ThreadTest4 窗口2 售出 13 號(hào)票 ThreadTest4 窗口2 售出 12 號(hào)票 ThreadTest4 窗口2 售出 11 號(hào)票 ThreadTest4 窗口2 售出 10 號(hào)票 ThreadTest4 窗口2 售出 9 號(hào)票 ThreadTest4 窗口2 售出 8 號(hào)票 ThreadTest4 窗口2 售出 7 號(hào)票 ThreadTest4 窗口3 售出 7 號(hào)票 ThreadTest4 窗口1 售出 5 號(hào)票 ThreadTest4 窗口2 售出 6 號(hào)票 ThreadTest4 窗口1 售出 3 號(hào)票 ThreadTest4 窗口4 售出 4 號(hào)票 ThreadTest4 窗口3 售出 4 號(hào)票 ThreadTest4 窗口1 售出 1 號(hào)票 ThreadTest4 窗口2 售出 2 號(hào)票 View Code

?

3. 線程同步

? ?多線程中涉及到共享數(shù)據(jù)時(shí),會(huì)出現(xiàn)線程安全問題。就上面的售票案例來說,若沒有加?synchronized?關(guān)鍵字,在多個(gè)線程同時(shí)使用ticket這個(gè)共享數(shù)據(jù)時(shí),會(huì)出現(xiàn)同一個(gè)ticket被使用兩次這樣的看似不可能的情況。另外還有一種情況,事實(shí)上ticket這個(gè)共享數(shù)據(jù)是類ThreadTest4對(duì)象t2中的變量,所以若是在主線程中添加t2.run();語句的話,也是會(huì)發(fā)生線程安全問題的。

? ?在Java里面,同步鎖的概念就是這樣的。任何一個(gè)Object Reference都可以作為同步鎖。我們可以把Object Reference理解為對(duì)象在內(nèi)存分配系統(tǒng)中的內(nèi)存地址。

1 class ThreadTest5 implements Runnable{ 2 private int ticket=20; 3 public void run(){ 4 while(ticket>0){ 5 String threadName = Thread.currentThread().getName(); 6 //同步代碼塊(越小越好) 7 synchronized(this){ 8 if(ticket>0){ 9 System.out.println(threadName + " sales ticket "+ticket); 10 ticket--; 11 } 12 } 13 } 14 } 15 } 16 17 public class Demo3{ 18 public static void main(String[] args){ 19 ThreadTest5 t = new ThreadTest5(); 20 (new Thread(t, "窗口A")).start(); 21 (new Thread(t, "窗口B")).start(); 22 (new Thread(t, "窗口C")).start(); 23 (new Thread(t, "窗口D")).start(); 24 } 25 }

運(yùn)行結(jié)果

窗口A sales ticket 20 窗口A sales ticket 19 窗口A sales ticket 18 窗口A sales ticket 17 窗口A sales ticket 16 窗口A sales ticket 15 窗口A sales ticket 14 窗口A sales ticket 13 窗口A sales ticket 12 窗口A sales ticket 11 窗口A sales ticket 10 窗口D sales ticket 9 窗口D sales ticket 8 窗口D sales ticket 7 窗口D sales ticket 6 窗口D sales ticket 5 窗口D sales ticket 4 窗口D sales ticket 3 窗口C sales ticket 2 窗口B sales ticket 1 View Code

(1)同步代碼塊

synchronized(類或?qū)ο?{//需要同步的代碼段 }

(2)同步函數(shù)

(非static的情況)

public synchronized void fun(){//代碼段 }

等價(jià)于(調(diào)用此同步函數(shù)的對(duì)象作為此同步函數(shù)的同步鎖)

public void fun() {synchronized(this) {//代碼段 } }

(static的情況)

public static synchronized void fun() {//代碼段 }

靜態(tài)變量或靜態(tài)方法加載到內(nèi)存中時(shí),內(nèi)存中沒有本類對(duì)象,但一定有了該類對(duì)應(yīng)的字節(jié)碼文件(類名.class),該對(duì)象的類型是class。靜態(tài)同步函數(shù)使用的同步鎖是所在類的字節(jié)碼文件。

?

線程同步的前提:

  1)2個(gè)或2個(gè)以上的線程

  2)使用同一把鎖
保證同步中只有一個(gè)線程在運(yùn)行。

好處:解決線程安全問題
弊端:多個(gè)線程需要判斷鎖,消耗資源

?

4. 線程通信

經(jīng)典的生產(chǎn)者和消費(fèi)者問題

假設(shè)倉庫中只能存放一件產(chǎn)品,生產(chǎn)者將生產(chǎn)出來的產(chǎn)品放入倉庫,消費(fèi)者將倉庫中的產(chǎn)品取走消費(fèi)。如果倉庫中沒有產(chǎn)品,則生產(chǎn)者可以將產(chǎn)品放入倉庫,否則停止生產(chǎn)并等待,直到倉庫中的產(chǎn)品被消費(fèi)者取走為止。如果倉庫中放有產(chǎn)品,則消費(fèi)者可以將產(chǎn)品取走消費(fèi),否則停止消費(fèi)并等待,直到倉庫中再次放入產(chǎn)品為止。顯然,這是一個(gè)同步問題,生產(chǎn)者和消費(fèi)者共享同一資源,并且,生產(chǎn)者和消費(fèi)者之間彼此依賴,互為條件向前推進(jìn)

4.1 synchronized和wait、notify、notifyAll

?wait()?使得當(dāng)前線程必須要等待,并釋放對(duì)鎖的擁有權(quán),等到另外一個(gè)線程調(diào)用notify()或者notifyAll()方法

?notify()?會(huì)喚醒一個(gè)等待當(dāng)前對(duì)象的鎖的線程

?notifyAll()?喚醒所有一個(gè)等待當(dāng)前對(duì)象的鎖的線程

一個(gè)小比較
  當(dāng)線程調(diào)用了wait()方法時(shí),它會(huì)釋放掉對(duì)象的鎖。
  另一個(gè)會(huì)導(dǎo)致線程暫停的方法:Thread.sleep(millisecond),它會(huì)導(dǎo)致線程睡眠指定的毫秒數(shù),但線程在睡眠的過程中是不會(huì)釋放掉對(duì)象的鎖的。

2 class Repository{ 3 private int count=0; //當(dāng)前倉庫存放商品數(shù)量 4 private int capacity=5; //倉庫容量 5 private String goodsName; //商品名稱 6 public Repository(String goodsName){ 7 this.goodsName = goodsName; 8 } 9 public void store(String threadName){ 10 synchronized(this){ 11 while(this.count>=this.capacity){ 12 System.out.println("[" + threadName + "]倉庫已達(dá)到最大容量 " + this.capacity + " 個(gè) !!"); 13 try{this.wait();} 14 catch(Exception e){} 15 } 16 this.count++; 17 System.out.println("[" + threadName + "]倉庫增加了一個(gè)"+this.goodsName+",現(xiàn)有"+this.goodsName+"["+this.count+"] 個(gè)"); 18 this.notifyAll(); 19 } 20 } 21 public void fetch(String threadName){ 22 synchronized(this){ 23 while(this.count<1){ 24 System.out.println("[" + threadName + "]倉庫沒有"+this.goodsName+"!!"); 25 try{ 26 this.wait(); 27 }catch(Exception e){ 28 29 } 30 } 31 this.count--; 32 System.out.println("[" + threadName + "]倉庫減少了一個(gè)"+this.goodsName+",現(xiàn)有"+this.goodsName+"["+this.count+"] 個(gè)"); 33 this.notifyAll(); 34 } 35 } 36 } 37 //生產(chǎn)者 38 class Producter implements Runnable{ 39 private Repository repository ; 40 public Producter(Repository repository){ 41 this.repository = repository; 42 } 43 public void run(){ 44 String threadName = Thread.currentThread().getName(); 45 while(true){ 46 try{ 47 //sleep 2秒模擬生產(chǎn)過程 48 Thread.sleep(1000); 49 }catch(Exception e){ 50 51 } 52 //把生產(chǎn)的商品存放到倉庫 53 repository.store(threadName); 54 } 55 } 56 } 57 //消費(fèi)者 58 class Consumer implements Runnable{ 59 private Repository repository ; 60 public Consumer(Repository repository){ 61 this.repository = repository; 62 } 63 public void run(){ 64 String threadName = Thread.currentThread().getName(); 65 while(true){ 66 //將商品從倉庫取出來 67 repository.fetch(threadName); 68 try{ 69 //sleep 4秒模擬消費(fèi)過程 70 Thread.sleep(2000); 71 }catch(Exception e){ 72 73 } 74 } 75 } 76 } 77 public class Thread06{ 78 public static void main(String[] args){ 79 Repository repository = new Repository("饅頭"); 80 81 Producter pro1 = new Producter(repository); 82 Consumer con1 = new Consumer(repository); 83 //生產(chǎn)者和消費(fèi)者各2個(gè) 84 (new Thread(pro1, "生產(chǎn)者A")).start(); 85 (new Thread(pro1, "生產(chǎn)者B")).start(); 86 (new Thread(con1, "消費(fèi)者1")).start(); 87 (new Thread(con1, "消費(fèi)者2")).start(); 88 } 89 }

其中一種運(yùn)行結(jié)果:

1 [消費(fèi)者1]倉庫沒有饅頭!! 2 [消費(fèi)者2]倉庫沒有饅頭!! 3 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[1] 個(gè) 4 [消費(fèi)者2]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[0] 個(gè) 5 [消費(fèi)者1]倉庫沒有饅頭!! 6 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[1] 個(gè) 7 [消費(fèi)者1]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[0] 個(gè) 8 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[1] 個(gè) 9 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[2] 個(gè) 10 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[3] 個(gè) 11 [消費(fèi)者2]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[2] 個(gè) 12 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[3] 個(gè) 13 [消費(fèi)者1]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[2] 個(gè) 14 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[3] 個(gè) 15 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[4] 個(gè) 16 [消費(fèi)者2]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[3] 個(gè) 17 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[4] 個(gè) 18 [消費(fèi)者1]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[3] 個(gè) 19 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[4] 個(gè) 20 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[5] 個(gè) 21 [生產(chǎn)者B]倉庫已達(dá)到最大容量 5 個(gè) !! 22 [消費(fèi)者2]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[4] 個(gè) 23 [生產(chǎn)者B]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[5] 個(gè) 24 [生產(chǎn)者A]倉庫已達(dá)到最大容量 5 個(gè) !! 25 [消費(fèi)者1]倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[4] 個(gè) 26 [生產(chǎn)者A]倉庫增加了一個(gè)饅頭,現(xiàn)有饅頭[5] 個(gè) 27 [生產(chǎn)者B]倉庫已達(dá)到最大容量 5 個(gè) !! 28 [生產(chǎn)者A]倉庫已達(dá)到最大容量 5 個(gè) !!

(運(yùn)行結(jié)果分析)

1)線程“消費(fèi)者1”調(diào)用repositoy.fetch()方法去倉庫取饅頭。進(jìn)入synchronized塊,剛一執(zhí)行while語句,結(jié)果 this.count<1 為真,直接就wait()進(jìn)入等待隊(duì)列,最后釋放了鎖 (就緒隊(duì)列[消費(fèi)者2,生產(chǎn)者A,生產(chǎn)者B],等待隊(duì)列[消費(fèi)者1]2)線程“消費(fèi)者2”同“消費(fèi)者1”的遭遇是相同的(對(duì)此,我們深表同情) (就緒隊(duì)列[生產(chǎn)者A,生產(chǎn)者B], 等待隊(duì)列[消費(fèi)者1,消費(fèi)者2]3)線程“生產(chǎn)者A”生產(chǎn)完商品后,調(diào)用repository.store()方法把商品存到了倉庫中。在store方法里,使用notifyAll方法喚醒了所有在沉睡wait的線程,最后釋放了鎖 (就緒隊(duì)列[生產(chǎn)者A,生產(chǎn)者B,消費(fèi)者1,消費(fèi)者2],等待隊(duì)列[]4)線程“消費(fèi)者2”從上次wait的地方開始執(zhí)行(從哪里跌倒,就從哪里爬起來)。同樣是while語句,但這次 this.count<1 不為真了,于是乎順利脫坑,接著執(zhí)行 this.count--,把倉庫僅有的一個(gè)饅頭給拿走了,走之前還不忘大喊一句“倉庫減少了一個(gè)饅頭,現(xiàn)有饅頭[0] 個(gè)”。同樣是notifyAll方法喚醒所有沉睡wait的線程,釋放鎖 (就緒隊(duì)列[生產(chǎn)者A,生產(chǎn)者B,消費(fèi)者1,消費(fèi)者2],等待隊(duì)列[]5)線程“消費(fèi)者1”辛辛苦苦搶到了鎖,終于能執(zhí)行syschronized塊代碼了。和“消費(fèi)者2”一樣,也是從上次wait的地方接著執(zhí)行,也是while語句,但不同的是 this.count<1 為真,線程“生產(chǎn)者A”生產(chǎn)存放到倉庫的僅有的一個(gè)饅頭被“消費(fèi)者2”給吃了,可以想象此時(shí)的“消費(fèi)者1”心里是萬念俱灰的。啥也別說了,接著沉睡wait吧。(釋放了鎖) (就緒隊(duì)列[生產(chǎn)者A,生產(chǎn)者B,消費(fèi)者2],等待隊(duì)列[消費(fèi)者1])
**** 在接下來的幾十個(gè)回合中,時(shí)而生產(chǎn)者線程奪得倉庫鎖,稱霸武林,時(shí)而消費(fèi)者線程奪得,笑傲江湖,倉庫商品也是時(shí)增時(shí)減,但總體上還是生產(chǎn)者線程搶到的次數(shù)多,因?yàn)樯a(chǎn)者夠快,當(dāng)消費(fèi)者還在花2秒鐘費(fèi)勁的消化時(shí),生產(chǎn)者早就1秒生產(chǎn)完畢,參與倉庫鎖的再次爭(zhēng)奪了,可見“天下武功,唯快不破” *****“倉庫里沒有饅頭為什么不通知我?”,線程“消費(fèi)者2”不滿“消費(fèi)者1”對(duì)倉庫情況的隱瞞不報(bào),“你要是早告訴我,我也就不用爭(zhēng)搶倉庫鎖,搶到了也沒用,里面根本就沒有饅頭,去了也是wait”。(第1、2步) “你還有臉說我,你把生產(chǎn)者A生產(chǎn)存放在倉庫僅有的一個(gè)饅頭吃了,你明知道倉庫再也沒有饅頭了,也不告訴我,還讓我傻了吧唧搶到倉庫鎖,去了也白搭”。“消費(fèi)者1”反駁道,它同樣也很委屈。(第4、5步) “管我什么事,搶倉庫鎖的有不只你一個(gè),我也去搶了,白費(fèi)了勁,還沒搶到
....”,線程“消費(fèi)者2”道。“要是倉庫沒有饅頭的時(shí)侯,只喚醒那幫生產(chǎn)者就好了”,線程“消費(fèi)者1”和“消費(fèi)者2”異口同聲的說道。

處理線程通信必須遵循一種原則:對(duì)于生產(chǎn)者,在生產(chǎn)者沒有生產(chǎn)之前,要通知消費(fèi)者等待;在生產(chǎn)者生產(chǎn)之后,馬上又通知消費(fèi)者消費(fèi);對(duì)于消費(fèi)者,在消費(fèi)者消費(fèi)之后,要通知生產(chǎn)者已經(jīng)消費(fèi)結(jié)束,需要繼續(xù)生產(chǎn)新的產(chǎn)品以供消費(fèi)。

4.2 Lock和Condition

Lock 實(shí)現(xiàn)提供了比使用 synchronized 方法和語句可獲得的更廣泛的鎖定操作。此實(shí)現(xiàn)允許更靈活的結(jié)構(gòu),可以具有差別很大的屬性,可以支持多個(gè)相關(guān)的 Condition 對(duì)象。

Condition 將 Object 監(jiān)視器方法(wait、notify 和 notifyAll)分解成截然不同的對(duì)象,以便通過將這些對(duì)象與任意 Lock 實(shí)現(xiàn)組合使用,為每個(gè)對(duì)象提供多個(gè)等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和語句的使用,Condition 替代了 Object 監(jiān)視器方法的使用

?

5. 停止線程的方法

interrupt() //停止線程 isInterrupt() //判斷線程是否停止

6. 守護(hù)線程和join方法

  守護(hù)線程是為其他線程提供便利服務(wù)的,當(dāng)全部的用戶線程結(jié)束后,守護(hù)線程才會(huì)隨JVM結(jié)束工作。?thread.setDaemon(true);?

public static void main(String[] args){ Thread t3 = new Thread(test2, "線程t3");t3.start();t3.join();  //主線程就此陷入等待,直到t3線程結(jié)束。 }

7. 線程優(yōu)先級(jí)和yield方法

線程的優(yōu)先級(jí)從低到高:1-10,優(yōu)先級(jí)高的的優(yōu)先執(zhí)行,每個(gè)新線程都繼承了父線程的優(yōu)先級(jí),常量:Thread.MIN_PRIORITY 值為1,Thread.MAX_PRIORITY 值為10,Thread.NORM_PRIORITY 值為5

void setPriority(priority) //設(shè)置線程優(yōu)先級(jí) int getPriority() //獲取線程優(yōu)先級(jí)

?yield()?線程從執(zhí)行狀態(tài)變成就緒狀態(tài)。

?

轉(zhuǎn)載于:https://www.cnblogs.com/lhat/p/6819170.html

總結(jié)

以上是生活随笔為你收集整理的【Java基础总结】多线程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。