線程間同步說的通俗一點講就是兩點:
1. 當某個線程處理好資料後能通知其他線程自己活幹完了,然後別的線程能使用它處理好的資料做其他事情。(Object.notify, Object.notifyAll)
2. 某個線程需要其他線程的計算結果時,需要等待知道別的線程把活幹完了,它拿到資料開始幹自己的活。(Object.wait)
java對並發的支援很全面,而且直接在基類Object裡面提供了支援,最常用的三種方法列舉如下(上面其實已經提到了):
1. Object.notify:通知某個線程自己活幹好了,兄弟可以開工了。某個調用了此對象的wait方法的線程將停止阻塞,返回。
2. Object.notifyAll:通知所有線程自己活幹好了。所有調用了此對象wait方法的線程都將停止阻塞,返回。
3. Object.wait:等待其它線程活幹完了,自己再開工。此方法將阻塞,直到某個線程調用了notify或者notifyAll為止。
下面是個簡單的例子,例子的用意是三個線程A、B、C一起幹活,每一次工序需要A先幹完然後B開工,B幹完然後C開工,然後進入下一個工序、如此反覆。
流程圖:
Java代碼
1 /** 2 * 並發列印類 3 * @author shun.li 4 */ 5 static class ConcurrentPrinter implements Runnable 6 { 7 8 //線程互斥變數 9 private static Object mutex = new Object();10 //當前獲得列印資格的線程的名字11 private static String currentName = ""; 12 public static void setCurrentName(String name) {13 currentName = name;14 }15 16 private String name; //本線程名字17 private String nextName;//下一個可列印的線程名18 private int count; //列印次數19 20 public ConcurrentPrinter(String name, String nextName, int count) {21 this.name = name;22 this.nextName = nextName;23 this.count = count;24 }25 26 /**27 * 列印資訊,列印次數為28 */29 public void print() {30 //:列印互斥,各個線程只有一個列印完了下一個才可以開始31 synchronized(mutex) {32 33 //:等待上一個線程通知自己可以列印34 while(currentName != name) {35 try {36 mutex.wait();37 } catch (InterruptedException e) { 38 return;39 }40 }41 //:列印42 for(int i = 0; i < count; ++i) {43 System.out.println(String.format("%1$04d:%2$s",i,name));44 }45 //設定可執行線程名為下一個46 currentName = nextName;47 //通知所有線程,名為currentName的線程符合條件,將開始列印48 mutex.notifyAll();49 } 50 }51 52 @Override53 public void run() {54 //各個線程先後執行列印任務100次55 for(int i = 0; i < 10; ++i) {56 this.print();57 }58 }59 }60 61 /**62 * @param args63 * @throws IOException 64 */65 public static void main(String[] args) {66 System.out.println("alala"); 67 68 //:建立3個線程,輪流列印69 Thread aThread = new Thread(new ConcurrentPrinter("A","B",3));70 Thread bThread = new Thread(new ConcurrentPrinter("B","C",3));71 Thread cThread = new Thread(new ConcurrentPrinter("C","A",3));72 ConcurrentPrinter.setCurrentName("A");73 aThread.start();74 bThread.start();75 cThread.start(); 76 }