可惡的Java多線程,一直沒搞懂同步的作用!
一直以為同步的時候只要鎖住對象就能順序執行了:
public class Test { final static byte[] b = new byte[0]; public static void main(String[] args) { Test t = new Test(); t.thread.start(); Test t2 = new Test(); t2.thread.start(); } Thread thread = new Thread(new Runnable() { @Override public void run() { test(); } }); public void test() { synchronized (this) { for (int n = 0; n < 100; n++) { System.out.println(thread.getName() + ":" + n); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }}
但是這樣是錯誤的!兩個線程還是交替執行!
查閱了很多資料才知道上面這個鎖是不正確的,兩個線程鎖住的this對象不是同一個,所以導致交叉執行。應該修改為:
public class Test { final static byte[] b = new byte[0]; public static void main(String[] args) { Test t = new Test(); t.thread.start(); t.test(); } Thread thread = new Thread(new Runnable() { @Override public void run() { test(); } }); public void test() { synchronized (this) { for (int n = 0; n < 100; n++) { System.out.println(thread.getName() + ":" + n); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }}
這樣的確就是順序執行了,因為函數鎖住的this對象是同一個,如果去除線程同步當然就會交叉執行啦。
但是我還有點不明白的是第一個例子錯誤的原因是其鎖住的對象不是同一個,但是如果我把this改為一個全域靜態常量還是不正確!理論上全域靜態常量整個運行周期記憶體中只會有一個對象阿!不明白為什麼還是不行!希望有高手可以解答。
其實我們用到同步多半是為了讓線程順序執行,比如在做Android開發的時候,我們通常希望前台顯示一個進度框,後台線程去執行下載動作,下載完之後前台線程在執行餘下操作如介面顯示。
這個時候其實可以使用線程的join()!
oin方法大家可以查下api,它的意思是等待當前線程執行完後執行完畢才執行其他線程。也就是說如果一個類中有這樣一個程式碼片段:
thread1.start();
thread2.start();
thread1.join();
thread2.join();
do something 1;
do something 2;
那麼這段代碼會等待兩個線程執行完畢後再執行 do something 1 和 do something 2,注意:必須先啟動所有線程,再join。如果啟動一個就join一個,結果是什嗎?對,那就會是等待thread1執行完再執行thread2,再執行後續代碼。