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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

java 总结几种线程异步转同步的方法

發布時間:2024/2/28 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 总结几种线程异步转同步的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自https://blog.csdn.net/Veson__/article/details/53898890

在做一款app的時候,用到了一個異步執行的api,而我想要的是同步執行,查了一些資料,對幾種情況下的線程同步做一下總結。


一、共享資源的同步

問題:當一個資源被多個線程訪問會發生錯誤,只能允許一個線程訪問時。

1.syschronized實現

使用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實現

    可以看出,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();?//獲得lock1??
  • ????????try?{??
  • ????????????while(num1?>?0)?{?//只有得到鎖的線程才能訪問??
  • ????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num1="?+?num1--);??
  • ????????????}??
  • ????????}?finally?{??
  • ????????????lock1.unlock();??
  • ????????}??
  • ??????????
  • ????????lock2.lock();//獲得lock2??
  • ????????try?{??
  • ????????????while(num2?>?0)?{??
  • ????????????????System.out.println(Thread.currentThread().getName()?+?"訪問num2="?+?num2--);??
  • ????????????}??
  • ????????}?finally?{??
  • ????????????//在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的優點(摘自:https://github.com/pzxwhc/MineKnowContainer/issues/16)

    lock在獲取鎖的過程可以被中斷。

    lock可以嘗試獲取鎖,如果鎖被其他線程持有,則返回 false,不會使當前線程休眠。

    lock在嘗試獲取鎖的時候,傳入一個時間參數,如果在這個時間范圍內,沒有獲得鎖,那么就是終止請求。

    synchronized 會自動釋放鎖,lock 則不會自動釋放鎖。


    二、異步轉同步

    問題:某些API是異步的,而我們想讓其同步。如:A、B兩個方法異步執行,由于某些需求,想讓A方法執行完之后再執行B方法。


    1.CountDownLatch解決

    使用CountDownLatch可以實現同步,它好比計數器,在實例CountDownLatch對象的時候傳入數字,每使用一次 .countDown() 方法計數減1,當數字減到0時, .await()方法后的代碼將可以執行,未到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"))?{?//t2線程??
  • ????????????try?{??
  • ????????????????Thread.sleep(5000);??
  • ????????????}?catch?(InterruptedException?e)?{??
  • ????????????????e.printStackTrace();??
  • ????????????}??
  • ????????????this.setNumber();??
  • ????????????latch.countDown();?//計數減1??
  • ????????}??
  • ????????else?if(Thread.currentThread().getName().equals("Thread-1")){?//t1線程??
  • ????????????try?{??
  • ????????????????latch.await();?//阻塞等待計數為0??
  • ????????????}?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之前執行結束,而t2執行的時間卻比t1長,故使用CountDown對t1進行阻塞等待t2完成。

    此外,也可以給await(設置參數),到達一定時間計數未變為0也可執行。




    ********其他方法待學習*******


    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的java 总结几种线程异步转同步的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

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