Java Thread Programming 1.8.3 – Inter-thread Communication
來源:互聯網
上載者:User
CubbyHole ExampleThe class CubbyHole (see Listing 8.9) simulates a cubbyhole. A cubbyhole is a slot that can have only one item in it at a time. One thread puts an item into the slot and another thread takes it out. If a thread tries to put an item into a cubbyhole that is already occupied, the thread blocks until the slot is available. If a thread tries to remove an item from an empty cubbyhole, the thread blocks until an item is added. In this example, the slot is a reference to an object. This technique allows objects to be handed off from one thread to another in a thread-safe manner. CubbyHole是指一個通道,某一時刻只能容納一個東西,一個線程放,另一個線程取。如果已經有東西,不能再放,直到東西被取出。如果沒有東西,則不能取,直到放進去新東西。下面給出一個安全執行緒的解決方案:
CubbyHole.java
/* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter8; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */public class CubbyHole {
private Object obj; public CubbyHole() { obj = null; } public synchronized void putIn(Object obj) throws InterruptedException{ print("putIn() ... begin");
while(this.obj != null){//等待,直到資料被取出 print("putIn() wait ... begin");
wait(); print("putIn() wait ... end"); } this.obj = obj;//添加新對象
notifyAll();//通知其它線程:有對象可取 print("putIn() ... end"); } public synchronized Object takeOut()throws InterruptedException{ print("takeOut() ... begin");
while(obj == null){//等待,直到有資料可以取 print("takeOut() wait ... begin");
wait(); print("takeOut() wait ... end"); } Object temp = obj;
obj = null;//將原資料清空
notifyAll();//通知其它線程:資料已取出,可填新資料 print("takeOut() ... end"); return temp; } public void print(String msg){ String temp = Thread.currentThread().getName(); System.out.println(temp + " - " + msg); } }
CubbyHoleMain.java/* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter8; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */public class CubbyHoleMain { public static void print(String msg){ String temp = Thread.currentThread().getName(); System.out.println(temp + " - " + msg); } public static void main(String[] args) { final CubbyHole ch = new CubbyHole(); Runnable runA = new Runnable(){ public void run(){ try{ Thread.sleep(500);//故意晚一些執行,讓其它線程先取資料 String str; str="multithreads"; ch.putIn(str);//可一直存 print("run() putIn() " + str); str = "programming"; ch.putIn(str); print("run() putIn() " + str); str = "with java"; ch.putIn(str); print("run() putIn() " + str); }catch(InterruptedException e){ print("exception " + e.getMessage()); } } }; Runnable runB = new Runnable(){ public void run(){ try{ Object obj; obj = ch.takeOut(); print("run() takeOut() " + obj);
Thread.sleep(500);//先取,後存
obj = ch.takeOut();//可一直取 print("run() takeOut() " + obj); obj = ch.takeOut(); print("run() takeOut() " + obj); }catch(InterruptedException e){ print("exception " + e.getMessage()); } } }; Thread threadA = new Thread(runA,"threadA"); threadA.start(); Thread threadB = new Thread(runB,"threadB"); threadB.start(); }} 輸出結果:threadB - takeOut() ... beginthreadB - takeOut() wait ... beginthreadA - putIn() ... beginthreadA - putIn() ... endthreadB - takeOut() wait ... endthreadB - takeOut() ... endthreadB - run() takeOut() multithreadsthreadA - run() putIn() multithreadsthreadA - putIn() ... beginthreadA - putIn() ... endthreadA - run() putIn() programmingthreadA - putIn() ... beginthreadA - putIn() wait ... beginthreadB - takeOut() ... beginthreadB - takeOut() ... endthreadB - run() takeOut() programmingthreadB - takeOut() ... beginthreadB - takeOut() wait ... beginthreadA - putIn() wait ... endthreadA - putIn() ... endthreadA - run() putIn() with javathreadB - takeOut() wait ... endthreadB - takeOut() ... endthreadB - run() takeOut() with java
Using join() to Wait for a Thread to DieThe join() method of Thread can be used to cause the current thread to block waiting for the specified thread to die. This is a relatively crude form of inter-thread communication, but on occasion it can be useful. If threadX runs the code join()方法使當前線程阻塞,直到指定的線程死亡。 try {
threadY.join()
} catch ( InterruptedException x ) {
}
threadX will block waiting for threadY to die. If threadX is interrupted while inside join(), it will throw an InterruptedException. There are three versions of the join() method available in Thread, all of which are public: join(), join(long), and join(long, int). Additionally, none of these methods can be overridden in a subclass because they are all declared final.
在Thread類中,提供了三個函數:join(),join(long),join(long,int),都被聲明為final,不可被子類override
join()public final void join() throws InterruptedException The join() method causes the current thread to block and wait an unlimited amount of time for this thread to die. The current thread will throw an InterruptedException if interrupted while waiting for the specified thread to die. join()阻塞當前線程直至其死亡,如果等待時被interrupted,會拋出InterruptedException
join(long) public final synchronized void join(long msTimeout) throws InterruptedException, IllegalArgumentException // RuntimeException
The join(long) method causes the current thread to block and wait up to msTimeout milliseconds for the specified thread to die. If msTimeout is 0, the current thread will never time out and will wait forever for the specified thread to die (just like join()). If msTimeout is less than 0, an IllegalArgumentException is thrown. The current thread will throw an InterruptedException if interrupted while waiting for the specified thread to die.
join(long)使當前線程阻塞一定時間(毫秒)等待其死亡,如果設定時間為0,則無限等待不會逾時,如果參數小於0,會拋出IllegalArgumentException異常
join(long, int)精確到納秒,一般虛擬機器未實現此方法
JoinDemo/* * Created on 2005-7-14 * * Java Thread Programming - Paul Hyde * Copyright ? 1999 Sams Publishing * Jonathan Q. Bo 學習筆記 * */package org.tju.msnrl.jonathan.thread.chapter8; /** * @author Jonathan Q. Bo from TJU MSNRL * * Email:jonathan.q.bo@gmail.com * Blog:blog.csdn.net/jonathan_q_bo * blog.yesky.net/jonathanundersun * * Enjoy Life with Sun! * */ public class JoinDemo { /** * 產生一個線程 * @param name 線程名 * @param napTime 線程存活時間 * @return 返回新產生的線程 */ public static Thread launch(String name, long napTime){ final long sleepTime = napTime; Runnable run = new Runnable(){ public void run(){ try{ print("run() ... begin"); Thread.sleep(sleepTime); }catch(InterruptedException e){ print("interrupted"); }finally{ print("run() ... end"); } } }; Thread thread = new Thread(run,name); thread.start();//開始執行 return thread; } public static void print(String msg){ String temp = Thread.currentThread().getName(); System.out.println(temp + " - " + msg); } public static void main(String[] args) { Thread[] t = new Thread[3]; t[0] = launch("threadA",2000); t[1] = launch("threadB",1000); t[2] = launch("threadC",3000); for(int i = 0; i < t.length; i++){ try{ String index = "t[" + i + "]"; String name = t[i].getName(); print(name + " is alive ? " + t[i].isAlive()); print(name + " begin join"); long startTime = System.currentTimeMillis();
t[i].join(); long endTime = System.currentTimeMillis(); print(name + " end join, costs " + (endTime - startTime) + "ms"); }catch(InterruptedException e){ e.printStackTrace(); } } } }
輸出結果:main - threadA is alive ? truemain - threadA begin jointhreadA - run() ... beginthreadB - run() ... beginthreadC - run() ... beginthreadB - run() ... endthreadA - run() ... endmain - threadA end join, costs 2000msmain - threadB is alive ? falsemain - threadB begin joinmain - threadB end join, costs 0msmain - threadC is alive ? truemain - threadC begin jointhreadC - run() ... endmain - threadC end join, costs 1000ms