国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

《Java并發(fā)編程實(shí)戰(zhàn)》課程筆記(九)

這篇具有很好參考價(jià)值的文章主要介紹了《Java并發(fā)編程實(shí)戰(zhàn)》課程筆記(九)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Semaphore:如何快速實(shí)現(xiàn)一個(gè)限流器?

信號(hào)量模型

  • 信號(hào)量模型還是很簡(jiǎn)單的,可以簡(jiǎn)單概括為:一個(gè)計(jì)數(shù)器,一個(gè)等待隊(duì)列,三個(gè)方法。
    《Java并發(fā)編程實(shí)戰(zhàn)》課程筆記(九)
  • 在信號(hào)量模型里,計(jì)數(shù)器和等待隊(duì)列對(duì)外是透明的,所以只能通過(guò)信號(hào)量模型提供的三個(gè)方法來(lái)訪問(wèn)它們,這三個(gè)方法分別是:init()、down() 和 up()。
    • init():設(shè)置計(jì)數(shù)器的初始值。
    • down():計(jì)數(shù)器的值減 1;如果此時(shí)計(jì)數(shù)器的值小于 0,則當(dāng)前線程將被阻塞,否則當(dāng)前線程可以繼續(xù)執(zhí)行。
    • up():計(jì)數(shù)器的值加 1;如果此時(shí)計(jì)數(shù)器的值小于或者等于 0,則喚醒等待隊(duì)列中的一個(gè)線程,并將其從等待隊(duì)列中移除。
    • 在 Java SDK 里面,信號(hào)量模型是由 java.util.concurrent.Semaphore 實(shí)現(xiàn)的,Semaphore 這個(gè)類能夠保證這三個(gè)方法都是原子操作。
    • 在 Java SDK 并發(fā)包里,down() 和 up() 對(duì)應(yīng)的則是 acquire() 和 release()。

如何使用信號(hào)量

快速實(shí)現(xiàn)一個(gè)限流器

  • 實(shí)現(xiàn)一個(gè)互斥鎖,僅僅是 Semaphore 的部分功能,Semaphore 還有?個(gè)功能是 Lock 不容易實(shí)現(xiàn)的,那就是:Semaphore 可以允許多個(gè)線程訪問(wèn)一個(gè)臨界區(qū)。
    • 比較常見(jiàn)的需求就是我們工作中遇到的各種池化資源,例如連接池、對(duì)象池、線程池等等。
    • 其中,數(shù)據(jù)庫(kù)連接池,在同一時(shí)刻,一定是允許多個(gè)線程同時(shí)使用連接池的,當(dāng)然,每個(gè)連接在被釋放前,是不允許其他線程使用的。
  • 所謂對(duì)象池,指的是一次性創(chuàng)建出 N 個(gè)對(duì)象,之后所有的線程重復(fù)利用這 N 個(gè)對(duì)象,當(dāng)然對(duì)象在被釋放前,也是不允許其他線程使用的。
    • 對(duì)象池,可以用 List 保存實(shí)例對(duì)象,這個(gè)很簡(jiǎn)單。
    • 但關(guān)鍵是限流器的設(shè)計(jì),這里的限流,指的是不允許多于 N 個(gè)線程同時(shí)進(jìn)入臨界區(qū)。
    • 那如何快速實(shí)現(xiàn)?個(gè)這樣的限流器呢?如果我們把計(jì)數(shù)器的值設(shè)置成對(duì)象池里對(duì)象的個(gè)數(shù) N,就能完美解決對(duì)象池的限流問(wèn)題了。
      import java.util.List;
      import java.util.Vector;
      import java.util.concurrent.Semaphore;
      import java.util.function.Function;
      
      public class ObjPool<T, R> {
          final List<T> pool;
          // ?信號(hào)量實(shí)現(xiàn)限流器
          final Semaphore semaphore;
          // 構(gòu)造函數(shù)
          ObjPool(int size, T t) {
              pool = new Vector<T>(){};
              for (int i = 0; i < size; i++) {
                  pool.add(t);
              }
              semaphore = new Semaphore(size);
          }
      
          // 利?對(duì)象池的對(duì)象,調(diào)? func
          // function 的作用是轉(zhuǎn)換,將一個(gè)值轉(zhuǎn)為另外一個(gè)值
          R exec(Function<T, R> function) throws InterruptedException {
              T t = null;
              semaphore.acquire();
              try {
                  t = pool.remove(0);
                  return function.apply(t);
              } finally {
                  pool.add(t);
                  semaphore.release();
              }
          }
      
          public static void main(String[] args) throws InterruptedException {
              // 創(chuàng)建對(duì)象池
              ObjPool<Long, String> objPool = new ObjPool<Long, String>(10, 2L);
              // 通過(guò)對(duì)象池獲取 t,之后執(zhí)?
              objPool.exec(t -> {
                  System.out.println(t);
                  return t.toString();
              });
          }
      }
      
    • 我們用一個(gè) List來(lái)保存對(duì)象實(shí)例,用 Semaphore 實(shí)現(xiàn)限流器。
    • 關(guān)鍵的代碼是 ObjPool 里面的 exec() 方法,這個(gè)方法里面實(shí)現(xiàn)了限流的功能。
      • 在這個(gè)方法里面,我們首先調(diào)用 acquire() 方法(與之匹配的是在 finally 里面調(diào)用 release() 方法),假設(shè)對(duì)象池的大小是 10,信號(hào)量的計(jì)數(shù)器初始化為 10,那么前 10 個(gè)線程調(diào)用 acquire() 方法,都能繼續(xù)執(zhí)行,而其他線程則會(huì)阻塞在 acquire() 方法上。
      • 我們?yōu)槊總€(gè)線程分配了一個(gè)對(duì)象 t(這個(gè)分配工作是通過(guò) pool.remove(0) 實(shí)現(xiàn)的),分配完之后會(huì)執(zhí)行一個(gè)回調(diào)函數(shù) func,而函數(shù)的參數(shù)正是前面分配的對(duì)象 t ;執(zhí)行完回調(diào)函數(shù)之后,它們就會(huì)釋放對(duì)象(這個(gè)釋放工作是通過(guò) pool.add(t) 實(shí)現(xiàn)的),同時(shí)調(diào)用 release() 方法來(lái)更新信號(hào)量的計(jì)數(shù)器。
      • 如果此時(shí)信號(hào)量里計(jì)數(shù)器的值小于等于 0,那么說(shuō)明有線程在等待,此時(shí)會(huì)自動(dòng)喚醒等待的線程。

文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-472092.html

到了這里,關(guān)于《Java并發(fā)編程實(shí)戰(zhàn)》課程筆記(九)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 《C++并發(fā)編程實(shí)戰(zhàn)》讀書(shū)筆記(3):并發(fā)操作的同步

    當(dāng)線程需要等待特定事件發(fā)生、或是某個(gè)條件成立時(shí),可以使用條件變量 std::condition_variable ,它在標(biāo)準(zhǔn)庫(kù)頭文件 condition_variable 內(nèi)聲明。 wait() 會(huì)先在內(nèi)部調(diào)用lambda函數(shù)判斷條件是否成立,若條件成立則 wait() 返回,否則解鎖互斥并讓當(dāng)前線程進(jìn)入等待狀態(tài)。當(dāng)其它線程調(diào)用

    2024年02月10日
    瀏覽(22)
  • 《C++并發(fā)編程實(shí)戰(zhàn)》讀書(shū)筆記(4):原子變量

    標(biāo)準(zhǔn)原子類型的定義位于頭文件 atomic 內(nèi)。原子操作的關(guān)鍵用途是取代需要互斥的同步方式,但假設(shè)原子操作本身也在內(nèi)部使用了互斥,就很可能無(wú)法達(dá)到期望的性能提升。有三種方法來(lái)判斷一個(gè)原子類型是否屬于無(wú)鎖數(shù)據(jù)結(jié)構(gòu): 所有標(biāo)準(zhǔn)原子類型( std::atomic_flag 除外,因?yàn)?/p>

    2024年02月10日
    瀏覽(28)
  • 《C++并發(fā)編程實(shí)戰(zhàn)》讀書(shū)筆記(1):線程管控

    包含頭文件 thread 后,通過(guò)構(gòu)建 std::thread 對(duì)象啟動(dòng)線程,任何可調(diào)用類型都適用于 std::thread 。 啟動(dòng)線程后,需要明確是等待它結(jié)束、還是任由它獨(dú)自運(yùn)行: 調(diào)用成員函數(shù) join() 會(huì)先等待線程結(jié)束,然后隸屬于該線程的任何存儲(chǔ)空間都會(huì)被清除, std::thread 對(duì)象不再關(guān)聯(lián)到已結(jié)

    2024年02月10日
    瀏覽(20)
  • Java并發(fā)編程實(shí)戰(zhàn)

    2023年06月19日
    瀏覽(20)
  • 《C++并發(fā)編程實(shí)戰(zhàn)》讀書(shū)筆記(2):線程間共享數(shù)據(jù)

    在C++中,我們通過(guò)構(gòu)造 std::mutex 的實(shí)例來(lái)創(chuàng)建互斥量,調(diào)用成員函數(shù) lock() 對(duì)其加鎖,調(diào)用 unlock() 解鎖。但通常更推薦的做法是使用標(biāo)準(zhǔn)庫(kù)提供的類模板 std::lock_guard ,它針對(duì)互斥量實(shí)現(xiàn)了RAII手法:在構(gòu)造時(shí)給互斥量加鎖,析構(gòu)時(shí)解鎖。兩個(gè)類都在頭文件 mutex 里聲明。 假設(shè)

    2024年02月10日
    瀏覽(11)
  • java并發(fā)編程之美第五章讀書(shū)筆記

    java并發(fā)編程之美第五章讀書(shū)筆記

    CopyOnWriteArrayList 線程安全的ArrayList,對(duì)其進(jìn)行的修改操作都是在底層的一個(gè)復(fù)制的數(shù)組(快照)進(jìn)行的,也就是寫(xiě)時(shí)復(fù)制策略 類圖 每一個(gè)對(duì)象里面有一個(gè)array數(shù)組進(jìn)行存放具體的元素,ReentrantLock獨(dú)占鎖對(duì)象用來(lái)保證同時(shí)只有一個(gè)線程對(duì)array進(jìn)行修改,這里只要記得ReentrantLock是獨(dú)占鎖

    2024年02月03日
    瀏覽(21)
  • Java并發(fā)編程學(xué)習(xí)筆記(一)線程的入門與創(chuàng)建

    Java并發(fā)編程學(xué)習(xí)筆記(一)線程的入門與創(chuàng)建

    認(rèn)識(shí) 程序由指令和數(shù)據(jù)組成,簡(jiǎn)單來(lái)說(shuō),進(jìn)程可以視為程序的一個(gè)實(shí)例 大部分程序可以同時(shí)運(yùn)行多個(gè)實(shí)例進(jìn)程,例如記事本、畫(huà)圖、瀏覽器等 少部分程序只能同時(shí)運(yùn)行一個(gè)實(shí)例進(jìn)程,例如QQ音樂(lè)、網(wǎng)易云音樂(lè)等 一個(gè)進(jìn)程可以分為多個(gè)線程,線程為最小調(diào)度單位,進(jìn)程則是作

    2024年02月16日
    瀏覽(48)
  • 【項(xiàng)目實(shí)戰(zhàn)】并發(fā)編程之Java中使用五種方式實(shí)現(xiàn)延時(shí)執(zhí)行調(diào)用

    To實(shí)現(xiàn)延時(shí)執(zhí)行調(diào)用,Java中可以使用Thread.sleep()方法。該方法接受一個(gè)以毫秒為單位的時(shí)間參數(shù),使當(dāng)前線程休眠指定的時(shí)間。在休眠期間,線程不會(huì)執(zhí)行任何操作。 以下是一個(gè)示例代碼塊,演示如何使用Thread.sleep()方法實(shí)現(xiàn)延時(shí)執(zhí)行調(diào)用:

    2024年02月15日
    瀏覽(19)
  • 多線程控制并發(fā)數(shù)目工具類Semaphore

    多線程控制并發(fā)數(shù)目工具類Semaphore

    在多線程編碼過(guò)程中,我們會(huì)用到多線程來(lái)提升運(yùn)行效率。比如我們的Executors創(chuàng)建線程池,程序盡可能的壓榨CPU資源來(lái)提升我們程序吞吐量。但是過(guò)度的使用線程,也會(huì)將我們CPU資源榨干,從而讓我們系統(tǒng)不能正常的提供服務(wù)。故今天我們引入JUC并發(fā)包下面的semaphore并發(fā)類,

    2024年02月02日
    瀏覽(14)
  • 【JAVA開(kāi)發(fā)面試】如何處理并發(fā)訪問(wèn)如何進(jìn)行代碼的單元測(cè)試Java多線程編程消息中間件設(shè)計(jì)模式技術(shù)難題是如何解決的

    【 點(diǎn)我-這里送書(shū) 】 本人詳解 作者:王文峰,參加過(guò) CSDN 2020年度博客之星,《Java王大師王天師》 公眾號(hào):JAVA開(kāi)發(fā)王大師,專注于天道酬勤的 Java 開(kāi)發(fā)問(wèn)題 中國(guó)國(guó)學(xué)、傳統(tǒng)文化和代碼愛(ài)好者的程序人生,期待你的關(guān)注和支持!本人外號(hào):神秘小峯 山峯 轉(zhuǎn)載說(shuō)明:務(wù)必注明

    2024年02月03日
    瀏覽(131)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包