生活随笔
收集整理的這篇文章主要介紹了
java 总结几种线程异步转同步的方法
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉載自https://blog.csdn.net/Veson__/article/details/53898890
在做一款app的時候,用到了一個異步執(zhí)行的api,而我想要的是同步執(zhí)行,查了一些資料,對幾種情況下的線程同步做一下總結。
一、共享資源的同步
問題:當一個資源被多個線程訪問會發(fā)生錯誤,只能允許一個線程訪問時。
1.syschronized實現(xiàn)
使用syschonized關鍵字可對某個塊或者方法進行限制訪問,即當一個線程獲得塊或者方法的訪問權后,其他線程將不能訪問。
[java]?view plaincopy
public?class?synchronize_test?implements?Runnable{??????int?num1?=?10;??????int?num2?=?10;??????int?num3?=?10;????????????public?void?synchonized_test()?{??????????synchronized(this)?{??????????????while(num1?>?0)?{???????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num1="?+?num1--);??????????????}??????????}??????????synchronized(this)?{???????????????while(num2?>?0)?{??????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num2="?+?num2--);??????????????}??????????}??????????while(num3?>?0)?{???????????????System.out.println(Thread.currentThread().getName()?+?"訪問num3="?+?num3--);??????????}??????????????????????????}??????@Override??????public?void?run()?{??????????synchonized_test();????????????????}??????????????public?static?void?main(String[]?args)?{??????????synchronize_test?sys?=?new?synchronize_test();??????????Thread?t1?=?new?Thread(sys);??????????Thread?t2?=?new?Thread(sys);??????????t1.start();??????????t2.start();??????????}??}??
當使用sychronized修飾某個方法(非static)時,作用對象將是這個方法所屬的對象,與同步塊同理。而如果synchronized修飾的是static方法或變量時,作
用對象將是static所在的類而非某個對象,因為static方法不屬于任何一個對象,而是屬于類。
2.Lock實現(xiàn)
可以看出,syschronized的作用的是對象或者類,這顯然不太靈活,而Lock則比其更加靈活一些。
[java]?view plaincopy
public?class?Lock_Test?implements?Runnable{??????int?num1?=?10;??????int?num2?=?10;??????Lock?lock1?=?new?ReentrantLock();??????Lock?lock2?=?new?ReentrantLock();????????????public?void?synchonized_test()?{??????????lock1.lock();???????????try?{??????????????while(num1?>?0)?{???????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num1="?+?num1--);??????????????}??????????}?finally?{??????????????lock1.unlock();??????????}????????????????????lock2.lock();??????????try?{??????????????while(num2?>?0)?{??????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num2="?+?num2--);??????????????}??????????}?finally?{????????????????????????????lock2.unlock();???????????}????????????????????????????????}????????????@Override??????public?void?run()?{??????????synchonized_test();????????????????}??????????public?static?void?main(String[]?args)?{????????????Lock_Test?lt?=?new?Lock_Test();??????????Thread?t1?=?new?Thread(lt);??????????Thread?t2?=?new?Thread(lt);??????????t1.start();??????????t2.start();????????}??}??
這里使用的是ReentrantLock,另外還有ReadWriteLock。
ReentranLock的優(yōu)點(摘自:https://github.com/pzxwhc/MineKnowContainer/issues/16)
lock在獲取鎖的過程可以被中斷。
lock可以嘗試獲取鎖,如果鎖被其他線程持有,則返回 false,不會使當前線程休眠。
lock在嘗試獲取鎖的時候,傳入一個時間參數,如果在這個時間范圍內,沒有獲得鎖,那么就是終止請求。
synchronized 會自動釋放鎖,lock 則不會自動釋放鎖。
二、異步轉同步
問題:某些API是異步的,而我們想讓其同步。如:A、B兩個方法異步執(zhí)行,由于某些需求,想讓A方法執(zhí)行完之后再執(zhí)行B方法。
1.CountDownLatch解決
使用CountDownLatch可以實現(xiàn)同步,它好比計數器,在實例CountDownLatch對象的時候傳入數字,每使用一次 .countDown() 方法計數減1,當數字減到0時, .await()方法后的代碼將可以執(zhí)行,未到0之前將一直阻塞等待。
[java]?view plaincopy
import?java.util.concurrent.CountDownLatch;????public?class?CountDownLatch_test?implements?Runnable{??????private?Integer?num?=?null;????????????private?static?CountDownLatch?latch;????????????public?void?setNumber()?{??????????num?=?1;??????}????????????public?int?getNumber()?{??????????return?this.num;??????}????????@Override??????public?void?run()?{??????????if(Thread.currentThread().getName().equals("Thread-0"))?{???????????????try?{??????????????????Thread.sleep(5000);??????????????}?catch?(InterruptedException?e)?{??????????????????e.printStackTrace();??????????????}??????????????this.setNumber();??????????????latch.countDown();???????????}??????????else?if(Thread.currentThread().getName().equals("Thread-1")){???????????????try?{??????????????????latch.await();???????????????}?catch?(InterruptedException?e)?{??????????????????e.printStackTrace();??????????????}??????????????System.out.println("num?=?"?+?this.getNumber());??????????}????????????????}????????public?static?void?main(String[]?args)?{??????????CountDownLatch_test?c?=?new?CountDownLatch_test();??????????latch?=?new?CountDownLatch(1);??????????Thread?t1?=?new?Thread(c);??????????Thread?t2?=?new?Thread(c);???????????t1.start();???????????t2.start();????????}????}??
如代碼所示,t1線程獲得num的值,t2線程給num賦值,顯然t2需要在t1之前執(zhí)行結束,而t2執(zhí)行的時間卻比t1長,故使用CountDown對t1進行阻塞等待t2完成。
此外,也可以給await(設置參數),到達一定時間計數未變?yōu)?也可執(zhí)行。
********其他方法待學習*******
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生
總結
以上是生活随笔為你收集整理的java 总结几种线程异步转同步的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。