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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java基础----线程

發布時間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java基础----线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、進程與線程

進程process)是一個可并發執行的具有獨立功能的程序(program)關于某個數據集合的一次執行過程,也是操作系統進行資源分配和保護的基本單位。

線程thread)是操作系統進程中能夠獨立執行的實體(控制流),是處理器調度和分派的基本單位。

比如word進程中有拼寫檢查、語法檢查很多線程。

二、Java的線程實現

????????在Java中如果要想進行多線程代碼的實現有兩種方式:

??????????????????·繼承Thread類

??????????????????·實現Runnable接口

1.1、繼承Thread類

Thread類聲明如下

public class Thread extends Object implements Runnable {public Thread() //構造方法public Thread(String name) //name指定線程名public Thread(Runnable target) //target指定線程的目標對象public Thread(Runnable target, String name)public void run() //描述線程操作的線程體public final String getName() //返回線程名public final void setName(String name) //設置線程名public static int activeCount() //返回當前活動線程個數public static Thread currentThread() //返回當前執行線程對象public Sting toString() //返回線程的字符串信息,包括名字、優先級和線程組public synchronized void start() //啟動已創建的線程對象 }

當一個類需要按照多線程的方式處理時,可以讓這個類直接繼承自Thread類即可,而且繼承的時候要覆寫好Thread類中提供的run()方法:

//聲明自定義線程類繼承Thread類實現奇數/偶數序列線程并發執行。public class NumberThread extends Thread {private int k; // 序列初始值public NumberThread(String name, int k) {super(name);this.k = k;}public NumberThread(String name) {this(name, 0);}public void run() // 覆蓋run方法的線程體{int i = k;System.out.print("\n" + this.getName() + ": ");while (i < 50) {System.out.print(i + " ");i += 2;}System.out.println(this.getName() + "結束!");}public static void main(String args[]) {NumberThread thread_odd = new NumberThread("奇數線程", 1); // 創建線程對象NumberThread thread_even = new NumberThread("偶數線程", 2);// thread_odd.setPriority(10); //設置優先級為最高thread_odd.start(); // 啟動線程對象thread_even.start();System.out.println("currentThread=" + Thread.currentThread().getName()); // 獲得當前線程對象名System.out.println("activeCount=" + thread_even.activeCount());System.out.println("main Priority="+ Thread.currentThread().getPriority()); // 獲得當前線程對象的優先級} }

啟動一個線程并不是依靠run()方法而是start()方法。此時通過start()方法執行線程的操作,操作中可以發現,每一個線程間都屬于交替的運行狀態,即:所有的線程都是交替運行的,且:那個線程搶到了CPU資源,那個線程就執行。

1.2實現Runnable接口

Runnable接口定義如下:

public interfaceRunnable{public void run() ;}

線程實現的第二種手段,實現Runnable接口來實現線程的操作類,???

//聲明自定義線程類實現Runnable接口實現奇數/偶數序列線程并發執行。public class NumberRunnable implements Runnable {private int k;public NumberRunnable(int k) {this.k = k;}public NumberRunnable() {this(0);}public void run() {int i = k;System.out.println();while (i < 50) {System.out.print(i + " ");i += 2;}System.out.println("結束!");}public static void main(String args[]) {NumberRunnable odd = new NumberRunnable(1); // 創建具有線程體的目標對象Thread thread_odd = new Thread(odd, "奇數線程"); // 以目標對象創建線程對象thread_odd.start();new Thread(new NumberRunnable(2), "偶數線程").start();System.out.println("currentThread=" + Thread.currentThread().getName());// 獲得當前線程對象名System.out.println("activeCount=" + Thread.activeCount());} }

線程確實已經實現了,但是需要注意的是,如果要想啟動一個線程肯定是Thread類中的start()方法完成,觀察Thread類中提供的構造方法:public Thread(Runnable target)通過構造發現,Thread類可以接收Runnable子類的對象,所以一切的線程都可以通過Thread類進行啟動。此時,通過Thread類進行了線程的啟動。

1.3、兩種實現方式的區別

????????對于Thread類和Runnable接口本身都是可以進行多線程的實現,那么兩者到底該使用誰更好呢?

??????????????1??繼承局限:使用Runnable接口可以避免單繼承的局限,而Thread類則有此局限;

????????????? 2??資源共享:使用Runnable接口實現多線程,可以實現資源(對象屬性)的共享,而Thread類卻無法實現。

??????????????????????????? |-此點只是相對而言,因為兩者的此種區別是有其應用范圍的。

范例:觀察資源共享

class MyThreadextends Thread {private int count = 5 ;public void run(){for(int x=0;x<50;x++){if(this.count>0){System.out.println("count= " + this.count--) ;}}}};public classThreadDemo03 {public static void main(String args[]){new MyThread().start() ;new MyThread().start() ;new MyThread().start() ;}};

現在的程序中每一個線程都各自占有各自的count屬性,所以并沒有達到資源共享的目的,如果換成Runnable呢?

class MyThread implements Runnable {private int count = 5 ;public void run(){for(int x=0;x<50;x++){if(this.count>0){System.out.println("count= " + this.count--) ;}}}};public classThreadDemo04 {public static void main(String args[]){MyThreadmt = new MyThread() ;new Thread(mt).start() ;new Thread(mt).start() ;new Thread(mt).start() ;}};

現在的代碼中可以發現,count屬性已經被所有的線程對象所共同擁有了。

class MyThread implements Runnable {private int count = 5 ;public void run(){for(int x=0;x<50;x++){if(this.count>0){System.out.println("count= " + this.count--) ;}}}};public classThreadDemo04 {public static void main(String args[]){MyThreadmt1= new MyThread() ;MyThread mt2 = new MyThread() ;MyThread mt3 = new MyThread() ;new Thread(mt1).start() ;new Thread(mt2).start() ;new Thread(mt3).start() ;}};

現在的程序中每一個線程都各自占有各自的count屬性,

1.4、兩種實現方式的聯系

?Thread類和Runnable接口中都可以發現,都必須同時覆寫run()方法,兩者的關系如何呢?觀察Thread類的定義:

public class Thread extends Object implements Runnable

其中有個Runable類型的變量

/* What will be run. */private Runnable target;

其中的run方法定義如下:

?public void run() // 描述線程操作的線程體{if (target != null)target.run(); // 執行目標對象的run()方法}}

發現Thread類實際上是Runnable的子類。而且Thread類也要去接收Runnable其他子類的對象,而且所有的線程中,通過Runnable接口實現的線程類里面都是編寫的具體功能,而并沒有所謂的CPU調度,而真正意義上的CPU調度由操作系統完成(通過Thread類的start()方法調用的)

Thread類要去協調操作系統,并且最終還要執行具體的線程主體的方法,而線程的主體呢,現在只專著于具體的功能實現,至于如何調度根本不管。Thread代理自定義的線程類的對象,如圖所示:

從圖的關系上可以清楚的發現,現在在線程中應用的設計思路就是代理設計模式。

三、線程的狀態

1、當執行new Thread(Runnable r)后,新創建出來的線程處于new狀態,這種線程不可能執行

2、當執行thread.start()后,線程處于runnable狀態,這種情況下只要得到CPU,就可以開始執行了。runnable狀態的線程,會接受JVM的調度,進入running狀態,但是具體何時會進入這個狀態,是隨機不可知的

3、running狀態中的線程最為復雜,可能會進入runnable、waiting、timed_waiting、blocked、dead狀態
如果CPU調度給了別的線程,或者執行了Thread.yield()方法,則進入runnable狀態,但是也有可能立刻又進入running狀態
如果執行了Thread.sleep(long),或者thread.join(long),或者在鎖對象上調用object.wait(long)方法,則會進入timed_waiting狀態
如果執行了thread.join(),或者在鎖對象上調用了object.wait()方法,則會進入waiting狀態
如果進入了同步方法或者同步代碼塊,沒有獲取鎖對象的話,則會進入blocked狀態

4、處于waiting狀態中的線程,如果是因為thread.join()方法進入等待的話,在目標thread執行完畢之后,會回到runnable狀態;如果是因為object.wait()方法進入等待的話,在鎖對象執行object.notify()或者object.notifyAll()之后會回到runnable狀態

處于timed_waiting狀態中的線程,和waiting狀態中的差不多,只不過是設定時間到了,就會回到runnable狀態

5、處于blocked狀態中的線程,只有獲取了鎖之后,才會脫離阻塞狀態

6、當線程執行完畢,或者拋出了未捕獲的異常之后,會進入dead狀態,該線程結束

四、線程的操作方法

4.1、命名和取得

????????每一個線程實際上都可以為其設置名字,而且也可以取得每一個線程的名字:

??????????????????·設置線程名稱:public final void setName(String name)

??????????????????·取得線程名稱:public final String getName()

??????????????????·取得當前線程:public static Thread currentThread()

??????????????????? 返回當前活動線程個數 public static int activeCount()

?????? 除了以上的設置名稱的方法外,在Thread類中也提供了兩個構造方法:

??????????????????·public Thread(String name)

??????????????????·public Thread(Runnable target,String name)

?每次java運行的時候,實際上都會啟動一個JVM的進程。那么既然是多線程的處理機制,實際上方法是在一個JVM上產生的一個線程而已

4.2、線程的休眠

所謂的休眠就是指減緩程序的運行速度,如果要休眠使用如下的方法:

??????????·休眠:public static void sleep(long millis) throwsInterruptedException,指定休眠時間

比如Thread.sleep(1000),當前線程睡眠1秒。需要知道的是,1秒后,線程是回到可執行狀態,并不是執行狀態,什么時候執行那是由虛擬機來決定的。所以sleep(1000)并不是在睡眠1秒后立即執行。

4.3、線程的優先級

????????實際上所有的線程啟動之后并不是立刻運行的,都需要等待CPU進行調度,但是調度的時候本身也是存在“優先”級的,如果優先級高則有可能最先被執行。

????????如果要想設置優先級可以使用:publicfinal void setPriority(int newPriority)

????????這個優先級需要接收一個整型的數字,這個數字只能設置三個內容:

??????????????????·最高優先級:public static final int MAX_PRIORITY??????? 1

??????????????????·中等優先級:public static final int NORM_PRIORITY?????? 5

??????????????????·最低優先級:public static final int MIN_PRIORITY????????10

問題:主方法的優先級是什么?

public classMainDemo {public static void main(String args[]){System.out.println(Thread.currentThread().getPriority()); //5System.out.println("MAX_PRIORITY" + Thread.MAX_PRIORITY) ;//10System.out.println("MIN_PRIORITY" + Thread.MIN_PRIORITY) ;//1System.out.println("NORM_PRIORITY" + Thread.NORM_PRIORITY) ;//5}};

主方法屬于中等優先級。

4.4、? join方法

線程有join方法,當線程1調用線程2的join方法時,線程1必須等待線程2執行完畢,線程1才能繼續往下執行。join方法主要用來將大問題分解成小問題,當小問題計算完成時,大問題才能繼續往下執行,這時候我們就可以利用join方法了。下面演示了一下線程的join方法。

public class TestJoin {public static void main(String[] args) {for(int i =0;i<10;i++){System.out.println(Thread.currentThread().getName()+" "+i);if(i==2){JoinThread jt=new JoinThread();jt.start();//主線程調用jt的join方法,主線程必須等待jt線程執行完才能繼續執行try {jt.join();} catch (InterruptedException e) {e.printStackTrace();}}}}}class JoinThread extends Thread {@Overridepublic void run() {for(int i = 0;i<10;i++){System.out.println(this.getName()+" "+i);}}}

運行結果如下:

main? 0
main? 1
main? 2
Thread-0? 0
Thread-0? 1
Thread-0? 2
Thread-0? 3
Thread-0? 4
Thread-0? 5
Thread-0? 6
Thread-0? 7
Thread-0? 8
Thread-0? 9
main? 3
main? 4
main? 5
main? 6
main? 7
main? 8
main? 9

4.5、yield方法
  

暫停當前正在執行的線程對象。
yield()只是使當前線程重新回到可執行狀態,所以執行yield()的線程有可能在進入到可執行狀態后馬上又被執行。yield()只能使同優先級或更高優先級的線程有執行的機會。

4.6、interrupt方法

interrupt()只是為線程設置一個中斷標記,一個線程對象被設置了中斷標記只有仍然可以運行,isAlive()返回true。實例方法isInterrupted()測試線程對象中的中斷標記,并不清除標記。靜態的interrupted()方法會測試當前執行的線程是否被中斷,并且在肯定的情況下,清除當前對象中斷標記,并返回true。

interrupt()不會中斷一個正在運行的線程.就是指線程如果正在運行的過程中, 去調用此方法是沒有任何反應的.為什么呢, 因為這個方法只是提供給被阻塞的線程, 即當線程調用了Object.wait, Thread.join, Thread.sleep三種方法之一的時候, 再調用interrupt方法, 才可以中斷剛才的阻塞而繼續去執行線程.

class ThreadDemo134 extends Thread {int count = 0;public void run() {System.out.println(getName() + " 將要運行...");while (!this.isInterrupted()) {System.out.println(getName() + " 運行中 " + count++);try {Thread.sleep(400); // 休眠400毫秒} catch (InterruptedException e) { // 退出阻塞態時將捕獲異常System.out.println(getName() + "從阻塞態中退出...");this.interrupt(); // 改變線程狀態,使循環結束}}System.out.println(getName() + " 已經終止!");}public static void main(String argv[]) throws InterruptedException {ThreadDemo134 ta = new ThreadDemo134();ta.setName("ThreadA");ta.start();Thread.sleep(2000);// 主線程休眠2000毫秒,等待其他線程執行System.out.println(ta.getName() + " 正在被中斷.....");// 2000毫秒過去后,main拿到cpu控制權。ta.interrupt(); // 中斷線程ThreadA} }

運行結果:

ThreadA 將要運行...
ThreadA 運行中 0
ThreadA 運行中 1
ThreadA 運行中 2
ThreadA 運行中 3
ThreadA 運行中 4
ThreadA 正在被中斷.....
ThreadA從阻塞態中退出...
ThreadA 已經終止!

五、線程的競爭關系與線程互斥

并發執行的交互線程間存在與時間有關的錯誤 // 銀行賬戶的存取款線程設計。public class Account // 賬戶類 {private String name; // 儲戶姓名private double balance; // 賬戶余額public Account(String name) {this.name = name;this.balance = 0;}public String getName() // 返回賬戶名{return name;}public double balance() // 查看賬戶余額{return balance;}public void put(double value) // 存款操作,參數為存入金額{if (value > 0)this.balance += value; // 存款操作使余額值增加}public double get(double value) // 取款操作,參數為取款金額,返回實際取到金額{if (value > 0) {if (value <= this.balance)this.balance -= value; // 取款操作使余額值減少else // 賬戶余額不夠所取時{value = this.balance; // 取走全部余額this.balance = 0;}return value; // 返回實際取款額}return 0;} }class Save extends Thread // 存款線程類 {private Account account; // 賬戶private double value; // 存款金額public Save(Account a1, double value) {this.account = a1;this.value = value;}public void run() {double howmatch = this.account.balance();// 查看賬戶余額try {sleep(1); // 花費時間,線程執行被打斷} catch (InterruptedException e) {}this.account.put(this.value);System.out.println(this.account.getName() + "賬戶:現有" + howmatch + ", 存入"+ this.value + ", 余額" + this.account.balance());} }class Fetch extends Thread // 取款線程類 {private Account account; // 賬戶private double value; // 取款金額public Fetch(Account a1, double value) {this.account = a1;this.value = value;}public void run() {double howmatch = this.account.balance();// 查看賬戶余額try {sleep(1); // 花費時間,線程執行被打斷} catch (InterruptedException e) {}System.out.println(this.account.getName() + "賬戶:現有" + howmatch + ", 取走"+ this.account.get(this.value) + ", 余額"+ this.account.balance());}public static void main(String args[]) {Account wang = new Account("Wang");(new Save(wang, 100)).start();(new Save(wang, 200)).start();(new Fetch(wang, 300)).start();(new Save(new Account("Li"), 100)).start();}}

錯誤結果:

Wang賬戶:現有0.0, 取走300.0, 余額0.0
Wang賬戶:現有0.0, 存入100.0, 余額0.0
Wang賬戶:現有0.0, 存入200.0, 余額0.0
Li賬戶:現有0.0, 存入100.0, 余額100.0

5.1、線程間的競爭關系

如果兩個線程要訪問同一資源,則線程間存在資源競爭關系。一個線程通過操作系統得到該資源,另一個將得不到。這時候一個線程的執行可能影響到同其競爭資源的其他線程。在極端情況下,被阻塞的線程永遠得不到訪問權,從而不能成功終止。資源競爭會出現兩個問題:

死鎖(deadlock) :一組進程獲得了部分資源,還想獲得其他進程占用的資源,最終所有的進程陷入死鎖。

饑餓(starvation):一個進程由于其他進程優先級總是優于它而被無限期拖延。

5.2、臨界區管理

每個進程中訪問臨界資源的那段程序稱為臨界區(Critical Section)(臨界資源是一次僅允許一個進程使用的共享資源)。每次只準許一個進程進入臨界區,進入后不允許其他進程進入。不論是硬件臨界資源,還是軟件臨界資源,多個進程必須互斥地對它進行訪問。
  多個進程中涉及到同一個臨界資源的臨界區稱為相關臨界區。
  進程進入臨界區的調度原則是: ①如果有若干進程要求進入空閑的臨界區,一次僅允許一個進程進入。②任何時候,處于臨界區內的進程不可多于一個。如已有進程進入自己的臨界區,則其它所有試圖進入臨界區的進程必須等待。③進入臨界區的進程要在有限時間內退出,以便其它進程能及時進入自己的臨界區。④如果進程不能進入自己的臨界區,則應讓出CPU,避免進程出現“忙等”現象。

5.3、Java線程互斥實現

Java采用synchronized關鍵字聲明一段程序為臨界區。synchronized有兩種用法:同步語句(代碼塊)、同步方法。

1.同步語句

synchronized(對象)

???語句

2.同步方法

synchronized?方法聲明

范例:使用同步代碼塊完成進程互斥

//互斥的存取款線程設計。public class SaveLock extends Thread // 帶互斥鎖的存款線程類 {private Account account; // 賬戶private double value; // 存款金額public SaveLock(Account a1, double value) {this.account = a1;this.value = value;}public void run() {synchronized (this.account) // 聲明臨界區,鎖定賬戶對象{double howmatch = this.account.balance();try {sleep(1); // 花費時間} catch (InterruptedException e) {}account.put(this.value);System.out.println(this.account.getName() + "賬戶:現有" + howmatch+ ", 存入" + this.value + ", 余額" + this.account.balance());}} }class FetchLock extends Thread // 帶互斥鎖的取款線程類 {private Account account;private double value;public FetchLock(Account a1, double value) {this.account = a1;this.value = value;}public void run() {synchronized (this.account) // 聲明臨界區,鎖定賬戶對象{double howmatch = this.account.balance();try {sleep(1); // 花費時間} catch (InterruptedException e) {}System.out.println(this.account.getName() + "賬戶:現有" + howmatch+ ", 取走" + this.account.get(this.value) + ", 余額"+ this.account.balance());}}public static void main(String args[]) {Account wang = new Account("Wang");(new SaveLock(wang, 100)).start();(new SaveLock(wang, 200)).start();(new FetchLock(wang, 300)).start();}}/** 程序運行結果如下: Wang賬戶:現有0.0, 存入100.0, 余額100.0 Wang賬戶:現有100.0, 存入200.0, 余額300.0* Wang賬戶:現有300.0, 取走300.0, 余額0.0*/

除了可以使用同步代碼塊之外還可以使用同步方法完成以上的操作。

5.4、一個方法的完整定義格式

???????? [public | protected | private ][static] [final] [synchronized]

????????返回值類型方法名稱(參數列表) [throws異常1,異常2,…]{

?????????????????? [return返回值 ;]

}

六、線程間的協作關系與線程同步

6.1、線程間的協作關系

發送線程與接收線程通過緩沖區實現數據傳遞

?

?

// 發送線程與接收線程。public class Buffer // 緩沖區 {private int value; // 共享變量public void put(int i) {value = i;}public int get() {return value;} }class Sender extends Thread // 發送線程類 {private Buffer buffer; // 用于交換數據的共享變量public Sender(Buffer buffer) // 指定緩沖區{this.buffer = buffer;}public void run() {for (int i = 1; i < 6; i++) // 連續向緩沖區發送若干數據{buffer.put(i);System.out.println("Sender put : " + i);try {sleep(1);} catch (InterruptedException e) {}}} }class Receiver extends Thread // 接收線程類 {private Buffer buffer;public Receiver(Buffer buffer) // 指定緩沖區{this.buffer = buffer;}public void run() {for (int i = 1; i < 6; i++) // 連續從緩沖區接收若干數據{System.out.println("\t\t\tReceiver get : " + buffer.get());try {sleep(1);} catch (InterruptedException e) {}}}public static void main(String args[]) {Buffer buffer = new Buffer();(new Sender(buffer)).start();(new Receiver(buffer)).start();}}/** 沒有sleep(1)語句時,程序運行結果如下: Sender put : 1 Sender put : 2 Sender put : 3 Sender* put : 4 Sender put : 5* * Receiver get : 5 Receiver get : 5 Receiver get : 5 Receiver get : 5 Receiver* get : 5* * * 有sleep(1)方法時,每次運行結果不確定,交替執行,間隔輸出,一種可能的運行結果如下: Sender put : 1 Receiver get : 1* Sender put : 2 Receiver get : 2 Sender put : 3 Sender put : 4 Receiver get :* 4 Sender put : 5 Receiver get : 5 Receiver get : 5*/

?6.2、線程同步

線程同步是解決協作關系的手段。線程同步是指兩個以上線程基于摸個條件來協調他們的活動。一個線程的執行依賴于另一個協作線程的消息或者信號,當一個線程沒有得到另一個線程的消息或者信號時,這需要等待。知道消息或者信號到達才能被喚醒。可理解線程A和B一塊配合,A執行到一定程度時要依靠B的某個結果,于是停下來,示意B運行;B依言執行,再將結果給A;A再繼續操作。

6.3、java 線程通信方法

Object類對線程的支持:在Object類中提供了以下的方法可以實現對線程的等待及喚醒的處理:

????????????????·等待:public final void wait() throws InterruptedException

?????????????? ?·等待:public final void wait(long timeout) throws InterruptedException

????????????????·喚醒:public final void notify(),喚醒第一個等待的線程

????????????????·喚醒:public final void notifyAll(),喚醒全部等待的線程

6.4、采用信號量和同步方法實現線程同步

//采用信號量和同步方法使發送線程與接收線程同步運行。public class BufferLock // 加互斥鎖的緩沖區 {private int value; // 共享變量private boolean isEmpty = true; // value是否為空的信號量public synchronized void put(int i) // 同步方法{while (!isEmpty) // 當value不空時,等待{try {this.wait(); // 使調用該方法的當前線程等待,即阻塞自己} catch (InterruptedException e) {}}value = i; // 當value空時,value獲得值System.out.println("Sender put : " + i);isEmpty = false; // 設置value為不空狀態notify(); // 喚醒其他等待線程}public synchronized int get() // 同步方法{while (isEmpty) // 當value空時,等待{try {this.wait();} catch (InterruptedException e) {}}isEmpty = true; // 設置value為空狀態,并返回值System.out.println("\t\t\tReceiver get : " + value);notify();return value;}public static void main(String args[]) {BufferLock buffer = new BufferLock();(new Sender(buffer)).start();(new Receiver(buffer)).start();}}class Sender extends Thread // 發送線程類 {private BufferLock buffer;public Sender(BufferLock buffer) {this.buffer = buffer;}public void run() {for (int i = 1; i < 6; i++) {buffer.put(i);}} }class Receiver extends Thread // 接收線程類 {private BufferLock buffer;public Receiver(BufferLock buffer) {this.buffer = buffer;}public void run() {for (int i = 1; i < 6; i++)buffer.get();}}

運行結果:

Sender? put : 1
???Receiver get : 1
Sender? put : 2
???Receiver get : 2
Sender? put : 3
???Receiver get : 3
Sender? put : 4
???Receiver get : 4
Sender? put : 5
???Receiver get : 5

?


?


?

?

總結

以上是生活随笔為你收集整理的java基础----线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。