自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

阻塞隊列—ArrayBlockingQueue源碼分析

開發(fā) 前端
ArrayBlockingQueue是一個阻塞隊列,內(nèi)部由ReentrantLock來實現(xiàn)線程安全,由Condition的await和signal來實現(xiàn)等待喚醒的功能。它的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,準(zhǔn)確地說是一個循環(huán)數(shù)組(可以類比一個圓環(huán)),所有的下標(biāo)在到達最大長度時自動從0繼續(xù)開始。

 前言


ArrayBlockingQueue 由數(shù)組支持的有界阻塞隊列,隊列基于數(shù)組實現(xiàn),容量大小在創(chuàng)建 ArrayBlockingQueue 對象時已經(jīng)定義好。 此隊列按照先進先出(FIFO)的原則對元素進行排序。支持公平鎖和非公平鎖,默認(rèn)采用非公平鎖。其數(shù)據(jù)結(jié)構(gòu)如下圖:

阻塞隊列—ArrayBlockingQueue源碼分析

 

  • 注:每一個線程在獲取鎖的時候可能都會排隊等待,如果在等待時間上,先獲取鎖的線程和請求一定先被滿足,那么這個鎖就是公平的。反之,這個鎖就是不公平的。公平的獲取鎖,也就是當(dāng)前等待時間最長的線程先獲取鎖

隊列創(chuàng)建

  1. BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(5); 

應(yīng)用場景

在線程池中有比較多的應(yīng)用,生產(chǎn)者消費者場景。

  • 先進先出隊列(隊列頭的是最先進隊的元素;隊列尾的是最后進隊的元素)
  • 有界隊列(即初始化時指定的容量,就是隊列最大的容量,不會出現(xiàn)擴容,容量滿,則阻塞進隊操作;容量空,則阻塞出隊操作)
  • 隊列不支持空元素
  • 公平性 (fairness)可以在構(gòu)造函數(shù)中指定。

此類支持對等待的生產(chǎn)者線程和使用者線程進行排序的可選公平策略。默認(rèn)情況下,不保證是這種排序。然而,通過在構(gòu)造函數(shù)將公平性 (fairness) 設(shè)置為 true 而構(gòu)造的隊列允許按照 FIFO 順序訪問線程。公平性通常會降低吞吐量,但也減少了可變性和避免了“不平衡性”。

工作原理

ArrayBlockingQueue是對BlockingQueue的一個數(shù)組實現(xiàn),它使用一把全局的鎖并行對queue的讀寫操作,同時使用兩個Condition阻塞容量為空時的取操作和容量滿時的寫操作。

基于 ReentrantLock 保證線程安全,根據(jù) Condition 實現(xiàn)隊列滿時的阻塞。

  1. final ReentrantLock lock; 
  2.  
  3. private final Condition notEmpty; 
  4.  
  5. private final Condition notFull; 

 Lock的作用是提供獨占鎖機制,來保護競爭資源;而Condition是為了更加精細(xì)地對鎖進行控制,它依賴于Lock,通過某個條件對多線程進行控制。

notEmpty表示“鎖的非空條件”。當(dāng)某線程想從隊列中取數(shù)據(jù)時,而此時又沒有數(shù)據(jù),則該線程通過notEmpty.await()進行等待;當(dāng)其它線程向隊列中插入了元素之后,就調(diào)用notEmpty.signal()喚醒“之前通過notEmpty.await()進入等待狀態(tài)的線程”。 同理,notFull表示“鎖的滿條件”。當(dāng)某線程想向隊列中插入元素,而此時隊列已滿時,該線程等待;當(dāng)其它線程從隊列中取出元素之后,就喚醒該等待的線程。

  • 試圖向已滿隊列中放入元素會導(dǎo)致放入操作受阻塞,直到BlockingQueue里有新的喚空間才會被醒繼續(xù)操作; 試圖從空隊列中檢索元素將導(dǎo)致類似阻塞,直到BlocingkQueue進了新貨才會被喚醒。

源碼分析

以下源碼分析基于JDK1.8

定義

ArrayBlockingQueue的類繼承關(guān)系如下:

  其包含的方法定義如下:

阻塞隊列—ArrayBlockingQueue源碼分析

 成員屬性

  1. /** 真正存入數(shù)據(jù)的數(shù)組 */ 
  2.    final Object[] items; 
  3.  
  4.    /** take,poll,peek or remove 的下一個索引 */ 
  5.    int takeIndex; 
  6.  
  7.    /** put,offer,or add 下一個索引 */ 
  8.    int putIndex; 
  9.  
  10.    /** 隊列中元素個數(shù) */ 
  11.    int count
  12.  
  13.    /** 可重入鎖 */ 
  14.    final ReentrantLock lock; 
  15.  
  16.    /** 如果數(shù)組是空的,在該Condition上等待 */ 
  17.    private final Condition notEmpty; 
  18.  
  19.    /** 如果數(shù)組是滿的,在該Condition上等待 */ 
  20.    private final Condition notFull; 
  21.  
  22.    /** 遍歷器實現(xiàn) */ 
  23.    transient Itrs itrs = null

 構(gòu)造函數(shù) 

  1. /** 
  2.     * 構(gòu)造函數(shù),設(shè)置隊列的初始容量 
  3.     */ 
  4.    public ArrayBlockingQueue(int capacity) { 
  5.        this(capacity, false); 
  6.    } 
  7.  
  8.    /** 
  9.     * 構(gòu)造函數(shù), 
  10.     * capacity and the specified access policy. 
  11.     * 
  12.     * @param capacity 設(shè)置數(shù)組大小 
  13.     * @param fair  設(shè)置是否為公平鎖 
  14.     * @throws IllegalArgumentException if {@code capacity < 1} 
  15.     */ 
  16.    public ArrayBlockingQueue(int capacity, boolean fair) { 
  17.        if (capacity <= 0) 
  18.            throw new IllegalArgumentException(); 
  19.        this.items = new Object[capacity]; 
  20.        // 是否為公平鎖,如果是的話,那么先到的線程先獲得鎖對象 
  21.        // 否則,由操作系統(tǒng)調(diào)度由哪個線程獲得鎖,一般為false,性能會比較高 
  22.        lock = new ReentrantLock(fair);  
  23.        notEmpty = lock.newCondition(); 
  24.        notFull =  lock.newCondition(); 
  25.    } 
  26.  
  27.    /** 
  28.     * 構(gòu)造函數(shù),帶有初始內(nèi)容的隊列 
  29.     */ 
  30.    public ArrayBlockingQueue(int capacity, boolean fair, 
  31.                              Collection<? extends E> c) { 
  32.        this(capacity, fair); 
  33.  
  34.        final ReentrantLock lock = this.lock; 
  35.        //加鎖的目的是為了其他CPU能夠立即看到修改 
  36.        //加鎖和解鎖底層都是CAS,會強制修改寫回主存,對其他CPU可見 
  37.        lock.lock(); // 要給數(shù)組設(shè)置內(nèi)容,先上鎖 
  38.        try { 
  39.            int i = 0; 
  40.            try { 
  41.                for (E e : c) { 
  42.                    checkNotNull(e); 
  43.                    items[i++] = e; // 依次拷貝內(nèi)容 
  44.                } 
  45.            } catch (ArrayIndexOutOfBoundsException ex) { 
  46.                throw new IllegalArgumentException(); 
  47.            } 
  48.            count = i; 
  49.            putIndex = (i == capacity) ? 0 : i; // 如果 putIndex大于數(shù)組大小,那么從0重寫開始 
  50.        } finally { 
  51.            lock.unlock(); // 最后一定要釋放鎖 
  52.        } 
  53.    } 

 入隊方法

add / offer / put,這三個方法都是往隊列中添加元素,說明如下:

  • add方法依賴于offer方法,如果隊列滿了則拋出異常,否則添加成功返回true;
  • offer方法有兩個重載版本,只有一個參數(shù)的版本,如果隊列滿了就返回false,否則加入到隊列中,返回true,add方法就是調(diào)用此版本的offer方法;另一個帶時間參數(shù)的版本,如果隊列滿了則等待,可指定等待的時間,如果這期間中斷了則拋出異常,如果等待超時了則返回false,否則加入到隊列中返回true;
  • put方法跟帶時間參數(shù)的offer方法邏輯一樣,不過沒有等待的時間限制,會一直等待直到隊列有空余位置了,再插入到隊列中,返回true
  1. /** 
  2.      * 添加一個元素,其實super.add里面調(diào)用了offer方法 
  3.      */ 
  4.     public boolean add(E e) { 
  5.         return super.add(e); 
  6.     } 
  7.  
  8.     /** 
  9.      * 加入成功返回 true,否則返回 false 
  10.      */ 
  11.     public boolean offer(E e) { 
  12.      // 創(chuàng)建插入的元素是否為null,是的話拋出NullPointerException異常 
  13.         checkNotNull(e); 
  14.         // 獲取“該阻塞隊列的獨占鎖” 
  15.         final ReentrantLock lock = this.lock; 
  16.         lock.lock(); // 上鎖 
  17.         try { 
  18.          // 如果隊列已滿,則返回false。 
  19.             if (count == items.length) // 超過數(shù)組的容量 
  20.                 return false
  21.             else { 
  22.              // 如果隊列未滿,則插入e,并返回true。 
  23.                 enqueue(e);  
  24.                 return true
  25.             } 
  26.         } finally { 
  27.          // 釋放鎖 
  28.             lock.unlock(); 
  29.         } 
  30.     } 
  31.  
  32.     /** 
  33.      * 如果隊列已滿的話,就會等待 
  34.      */ 
  35.     public void put(E e) throws InterruptedException { 
  36.         checkNotNull(e); 
  37.         final ReentrantLock lock = this.lock; 
  38.         lock.lockInterruptibly(); //和lock方法的區(qū)別是讓它在阻塞時可以拋出異常跳出 
  39.         try { 
  40.             while (count == items.length) 
  41.                 notFull.await(); // 這里就是阻塞了,要注意:如果運行到這里,那么它會釋放上面的鎖,一直等到 notify 
  42.             enqueue(e); 
  43.         } finally { 
  44.             lock.unlock(); 
  45.         } 
  46.     } 
  47.  
  48.     /** 
  49.      * 帶有超時事件的插入方法,unit 表示是按秒、分、時哪一種 
  50.      */ 
  51.     public boolean offer(E e, long timeout, TimeUnit unit) 
  52.         throws InterruptedException { 
  53.  
  54.         checkNotNull(e); 
  55.         long nanos = unit.toNanos(timeout); 
  56.         final ReentrantLock lock = this.lock; 
  57.         lock.lockInterruptibly(); 
  58.         try { 
  59.             while (count == items.length) { 
  60.                 if (nanos <= 0) 
  61.                     return false
  62.                 nanos = notFull.awaitNanos(nanos); // 帶有超時等待的阻塞方法 
  63.             } 
  64.             enqueue(e); // 入隊 
  65.             return true
  66.         } finally { 
  67.             lock.unlock(); 
  68.         } 
  69.     } 

 出隊方法

poll / take / peek,這幾個方法都是獲取隊列頂?shù)脑?,具體說明如下:

  • poll方法有兩個重載版本,第一個版本,如果隊列是空的,返回null,否則移除并返回隊列頭部元素;另一個帶時間參數(shù)的版本,如果棧為空則等待,可以指定等待的時間,如果等待超時了則返回null,如果被中斷了則拋出異常,否則移除并返回棧頂元素
  • take方法同帶時間參數(shù)的poll方法,但是不能指定等待時間,會一直等待直到隊列中有元素為止,然后移除并返回棧頂元素
  • peek方法只是返回隊列頭部元素,不移除
  1. // 實現(xiàn)的方法,如果當(dāng)前隊列為空,返回null 
  2.    public E poll() { 
  3.        final ReentrantLock lock = this.lock; 
  4.        lock.lock(); 
  5.        try { 
  6.            return (count == 0) ? null : dequeue(); 
  7.        } finally { 
  8.            lock.unlock(); 
  9.        } 
  10.    } 
  11. // 實現(xiàn)的方法,如果當(dāng)前隊列為空,一直阻塞 
  12.    public E take() throws InterruptedException { 
  13.        final ReentrantLock lock = this.lock; 
  14.        lock.lockInterruptibly(); 
  15.        try { 
  16.            while (count == 0) 
  17.                notEmpty.await(); // 隊列為空,阻塞方法 
  18.            return dequeue(); 
  19.        } finally { 
  20.            lock.unlock(); 
  21.        } 
  22.    } 
  23. // 帶有超時事件的取元素方法,否則返回null 
  24.    public E poll(long timeout, TimeUnit unit) throws InterruptedException { 
  25.        long nanos = unit.toNanos(timeout); 
  26.        final ReentrantLock lock = this.lock; 
  27.        lock.lockInterruptibly(); 
  28.        try { 
  29.            while (count == 0) { 
  30.                if (nanos <= 0) 
  31.                    return null
  32.                nanos = notEmpty.awaitNanos(nanos); // 超時等待 
  33.            } 
  34.            return dequeue(); // 取得元素 
  35.        } finally { 
  36.            lock.unlock(); 
  37.        } 
  38.    } 
  39.  
  40.    // 只是看一個隊列最前面的元素,取出是不擅長隊列中原來的元素,隊列為空時返回null 
  41.    public E peek() { 
  42.        final ReentrantLock lock = this.lock; 
  43.        lock.lock(); 
  44.        try { 
  45.            return itemAt(takeIndex); // 隊列為空時返回null 
  46.        } finally { 
  47.            lock.unlock(); 
  48.        } 
  49.    } 

 刪除元素方法

remove / clear /drainT,這三個方法用于從隊列中移除元素,具體說明如下:

  • remove方法用于移除某個元素,如果棧為空或者沒有找到該元素則返回false,否則從棧中移除該元素;移除時,如果該元素位于棧頂則直接移除,如果位于棧中間,則需要將該元素后面的其他元素往前面挪動,移除后需要喚醒因為棧滿了而阻塞的線程
  • clear方法用于整個棧,同時將takeIndex置為putIndex,保證棧中的元素先進先出;最后會喚醒最多count個線程,因為正常一個線程插入一個元素,如果喚醒超過count個線程,可能導(dǎo)致部分線程因為棧滿了又再次被阻塞
  • drainTo方法有兩個重載版本,一個是不帶個數(shù),將所有的元素都移除并拷貝到指定的集合中;一個帶個數(shù),將指定個數(shù)的元素移除并拷貝到指定的集合中,兩者的底層實現(xiàn)都是同一個方法。移除后需要重置takeIndex和count,并喚醒最多移除個數(shù)的因為棧滿而阻塞的線程。
  1. /** 
  2.     * 從隊列中刪除一個元素的方法。刪除成功返回true,否則返回false 
  3.     */ 
  4.    public boolean remove(Object o) { 
  5.        if (o == nullreturn false
  6.        final Object[] items = this.items; 
  7.        final ReentrantLock lock = this.lock; 
  8.        lock.lock(); 
  9.        try { 
  10.            if (count > 0) { 
  11.                final int putIndex = this.putIndex; 
  12.                int i = takeIndex; 
  13.                //從takeIndex開始往后遍歷直到等于putIndex 
  14.                do { 
  15.                    if (o.equals(items[i])) { 
  16.                        removeAt(i); // 真正刪除的方法 
  17.                        return true
  18.                    } 
  19.                    //走到數(shù)組末尾了又從頭開始,put時也按照這個規(guī)則來 
  20.                    if (++i == items.length) 
  21.                        i = 0; 
  22.                } while (i != putIndex); // 一直不斷的循環(huán)取出來做判斷 
  23.            } 
  24.            //如果數(shù)組為空,返回false 
  25.            return false
  26.        } finally { 
  27.            lock.unlock(); 
  28.        } 
  29.    } 
  30.  
  31. /** 
  32.     * 指定刪除索引上的元素. 
  33.     */ 
  34.    void removeAt(final int removeIndex) { 
  35.        // assert lock.getHoldCount() == 1; 
  36.        // assert items[removeIndex] != null
  37.        // assert removeIndex >= 0 && removeIndex < items.length; 
  38.        final Object[] items = this.items; 
  39.        if (removeIndex == takeIndex) { 
  40.            //如果移除的就是棧頂?shù)脑?nbsp;
  41.            items[takeIndex] = null
  42.            if (++takeIndex == items.length) 
  43.                takeIndex = 0; 
  44.            //元素個數(shù)減1 
  45.            count--; 
  46.            if (itrs != null
  47.                itrs.elementDequeued(); 
  48.        } else { 
  49.            // an "interior" remove 
  50.  
  51.            // 如果移除的是棧中間的某個元素,需要將該元素后面的元素往前挪動 
  52.            final int putIndex = this.putIndex; 
  53.            for (int i = removeIndex;;) { 
  54.                int next = i + 1; 
  55.                //到數(shù)組末尾了,從頭開始 
  56.                if (next == items.length) 
  57.                    next = 0; 
  58.                if (next != putIndex) { 
  59.                 //將后面一個元素復(fù)制到前面來 
  60.                    items[i] = items[next]; 
  61.                    i = next
  62.                } else { 
  63.                 //如果下一個元素的索引等于putIndex,說明i就是棧中最后一個元素了,直接將該元素置為null 
  64.                    items[i] = null
  65.                    //重置putIndex為i 
  66.                    this.putIndex = i; 
  67.                    break; 
  68.                } 
  69.            } 
  70.            count--; 
  71.            if (itrs != null
  72.             //通知itrs節(jié)點移除了 
  73.                itrs.removedAt(removeIndex); 
  74.        } 
  75.        //喚醒因為棧滿了而等待的線程 
  76.        notFull.signal(); // 有一個元素刪除成功,那肯定隊列不滿 
  77.    } 
  78.  
  79. /** 
  80.     * 清空隊列 
  81.     */ 
  82.    public void clear() { 
  83.        final Object[] items = this.items; 
  84.        final ReentrantLock lock = this.lock; 
  85.        lock.lock(); 
  86.        try { 
  87.            int k = count
  88.            if (k > 0) { 
  89.                final int putIndex = this.putIndex; 
  90.                int i = takeIndex; 
  91.                //從takeIndex開始遍歷直到i等于putIndex,將數(shù)組元素置為null 
  92.                do { 
  93.                    items[i] = null
  94.                    if (++i == items.length) 
  95.                        i = 0; 
  96.                } while (i != putIndex); 
  97.                //注意此處沒有將這兩個index置為0,只是讓他們相等,因為只要相等就可以實現(xiàn)棧先進先出了 
  98.                takeIndex = putIndex; 
  99.                count = 0; 
  100.                if (itrs != null
  101.                    itrs.queueIsEmpty(); 
  102.                //如果有因為棧滿了而等待的線程,則將其喚醒 
  103.                //注意這里沒有使用signalAll而是通過for循環(huán)來signal多次,單純從喚醒線程來看是可以使用signalAll的,效果跟這里的for循環(huán)是一樣的 
  104.                //如果有等待的線程,說明count就是當(dāng)前線程的最大容量了,這里清空了,最多只能put count次,一個線程只能put 1次,只喚醒最多count個線程就避免了 
  105.                //線程被喚醒后再次因為棧滿了而阻塞 
  106.                for (; k > 0 && lock.hasWaiters(notFull); k--) 
  107.                    notFull.signal(); 
  108.            } 
  109.        } finally { 
  110.            lock.unlock(); 
  111.        } 
  112.    } 
  113.  
  114.    /** 
  115.     * 取出所有元素到集合 
  116.     */ 
  117.    public int drainTo(Collection<? super E> c) { 
  118.        return drainTo(c, Integer.MAX_VALUE); 
  119.    } 
  120.  
  121.    /** 
  122.     * 取出所有元素到集合 
  123.     */ 
  124.    public int drainTo(Collection<? super E> c, int maxElements) { 
  125.        //校驗參數(shù)合法 
  126.        checkNotNull(c); 
  127.        if (c == this) 
  128.            throw new IllegalArgumentException(); 
  129.        if (maxElements <= 0) 
  130.            return 0; 
  131.        final Object[] items = this.items; 
  132.        final ReentrantLock lock = this.lock; 
  133.        lock.lock(); 
  134.        try { 
  135.         //取兩者之間的最小值 
  136.            int n = Math.min(maxElements, count); 
  137.            int take = takeIndex; 
  138.            int i = 0; 
  139.            try { 
  140.             //從takeIndex開始遍歷,取出元素然后添加到c中,直到滿足個數(shù)要求為止 
  141.                while (i < n) { 
  142.                    @SuppressWarnings("unchecked"
  143.                    E x = (E) items[take]; 
  144.                    c.add(x); 
  145.                    items[take] = null
  146.                    if (++take == items.length) 
  147.                        take = 0; 
  148.                    i++; 
  149.                } 
  150.                return n; 
  151.            } finally { 
  152.                // Restore invariants even if c.add() threw 
  153.                if (i > 0) { 
  154.                 //取完了,修改count減去i 
  155.                    count -= i; 
  156.                    takeIndex = take; 
  157.                    if (itrs != null) { 
  158.                        if (count == 0) 
  159.                         //通知itrs ??樟?nbsp;
  160.                            itrs.queueIsEmpty(); 
  161.                        else if (i > take) 
  162.                         //說明take中間變成0了,通知itrs 
  163.                            itrs.takeIndexWrapped(); 
  164.                    } 
  165.                    //喚醒在因為棧滿而等待的線程,最多喚醒i個,同上避免線程被喚醒了因為棧又滿了而阻塞 
  166.                    for (; i > 0 && lock.hasWaiters(notFull); i--) 
  167.                        notFull.signal(); 
  168.                } 
  169.            } 
  170.        } finally { 
  171.            lock.unlock(); 
  172.        } 
  173.    } 

 iterator / Itr / Itrs

Itr和Itrs都是ArrayBlockingQueue的兩個內(nèi)部類,如下:

阻塞隊列—ArrayBlockingQueue源碼分析

 iterator方法返回一個迭代器實例,用于實現(xiàn)for循環(huán)遍歷和部分Collection接口,該方法的實現(xiàn)如下: 

  1. public Iterator<E> iterator() { 
  2.  return new Itr(); 
  3.  
  4. Itr() { 
  5.  // assert lock.getHoldCount() == 0; 
  6.  lastRet = NONE; 
  7.  final ReentrantLock lock = ArrayBlockingQueue.this.lock; 
  8.     lock.lock(); 
  9.     try { 
  10.      if (count == 0) { 
  11.          //NONE和DETACHED都是常量 
  12.             cursor = NONE; 
  13.             nextIndex = NONE; 
  14.             prevTakeIndex = DETACHED; 
  15.         } else { 
  16.          //初始化各屬性 
  17.             final int takeIndex = ArrayBlockingQueue.this.takeIndex; 
  18.             prevTakeIndex = takeIndex; 
  19.             nextItem = itemAt(nextIndex = takeIndex); 
  20.             cursor = incCursor(takeIndex); 
  21.             if (itrs == null) { 
  22.              itrs = new Itrs(this); 
  23.             } else { 
  24.              //初始化Itrs,將當(dāng)前線程注冊到Itrs 
  25.                 itrs.register(this); // in this order 
  26.                 itrs.doSomeSweeping(false); 
  27.             } 
  28.             prevCycles = itrs.cycles; 
  29.             // assert takeIndex >= 0; 
  30.             // assert prevTakeIndex == takeIndex; 
  31.             // assert nextIndex >= 0; 
  32.             // assert nextItem != null
  33.      } 
  34.  } finally { 
  35.     lock.unlock(); 
  36.     } 
  37.  
  38. Itrs(Itr initial) { 
  39.  register(initial); 
  40.  
  41. //根據(jù)index計算cursor 
  42. private int incCursor(int index) { 
  43.  // assert lock.getHoldCount() == 1; 
  44.  if (++index == items.length) 
  45.   index = 0; 
  46.  if (index == putIndex) 
  47.   index = NONE; 
  48.  return index
  49.  
  50. /** 
  51. * 創(chuàng)建一個新的Itr實例時,會調(diào)用此方法將該實例添加到Node鏈表中 
  52. */ 
  53. void register(Itr itr) { 
  54.  //創(chuàng)建一個新節(jié)點將其插入到head節(jié)點的前面 
  55.  head = new Node(itr, head); 

 小結(jié)

ArrayBlockingQueue是一個阻塞隊列,內(nèi)部由ReentrantLock來實現(xiàn)線程安全,由Condition的await和signal來實現(xiàn)等待喚醒的功能。它的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,準(zhǔn)確地說是一個循環(huán)數(shù)組(可以類比一個圓環(huán)),所有的下標(biāo)在到達最大長度時自動從0繼續(xù)開始。

PS:以上代碼提交在 Github :

https://github.com/Niuh-Study/niuh-juc-final.git

 

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2020-11-25 14:28:56

DelayedWork

2020-11-24 09:04:55

PriorityBlo

2020-11-20 06:22:02

LinkedBlock

2023-12-28 07:49:11

線程池源碼應(yīng)用場景

2017-04-12 10:02:21

Java阻塞隊列原理分析

2025-01-14 00:00:00

Blocking隊列元素

2012-06-14 10:34:40

Java阻塞搜索實例

2025-04-03 07:41:55

API阻塞隊列數(shù)據(jù)

2023-12-15 09:45:21

阻塞接口

2025-04-02 01:20:00

阻塞隊列源碼

2022-06-30 08:14:05

Java阻塞隊列

2021-05-17 07:36:54

ArrayBlocki面試集合

2021-06-04 14:15:10

鴻蒙HarmonyOS應(yīng)用

2024-10-14 12:34:08

2024-02-20 08:16:10

阻塞隊列源碼

2022-09-26 00:48:14

線程池阻塞數(shù)據(jù)

2011-03-15 11:33:18

iptables

2021-09-22 14:36:32

鴻蒙HarmonyOS應(yīng)用

2014-08-26 11:11:57

AsyncHttpCl源碼分析

2023-12-05 13:46:09

解密協(xié)程線程隊列
點贊
收藏

51CTO技術(shù)棧公眾號