<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 關鍵字Synchronized 關鍵字`Synchronized`、`Object.wat()`和`Object.notify()`是在jdk1.5之前用的多線程同步控制的方式,jdk1.5之后就提供了如下的`java.util.concurrent`工具包(簡稱為`juc`并發工具包),可以利用如下的新的工具來實現多線程間的同步。 如下代碼,可以知道其使用場景及作用: ~~~ // 類T class T { // 靜態對象,是在類上的,只有一個 private static Object lock = new Object(); @SneakyThrows public void doSomething(){ // 鎖靜態對象,只有一個,是系統一個鎖 synchronized (lock){ lock.wait(); } } public void doSomething2(){ // 鎖類對象,只有一個,是同一個鎖 synchronized (T.class){ // 做一些事情 lock.notify(); } } // 修飾在實例方法上,實則是在調用對象上加鎖,調用對象不同則鎖不同 public synchronized void doSomething3(){ } // 修飾在靜態方法上,實則是在當前類對象上加鎖,只有一個鎖 public static synchronized void doSomething4(){ } } ~~~ ## 重入鎖 ReentrantLock ### 定義 重入鎖可以允許一個線程連續2次獲取同一把鎖,當然解鎖也需要解鎖2次。(關鍵字synchronized也是重入鎖) ### 重要方法 ![](https://img.kancloud.cn/a8/34/a834ba1b98630a1a75c474f00dd913ce_1098x370.png) * lock() 獲取鎖,如果鎖被占用,則等待 * lockInterruptibly() 獲取鎖,但優先響應中斷 可以利用中斷來直接退出等待鎖,釋放資源,防止死鎖 * tryLock() 嘗試獲取鎖,理解返回結果;獲取成功返回true,失敗返回false * tryLock(timeout,unit) 給定時間內嘗試獲取鎖 * unlock() 釋放鎖 ### 公平鎖 構造方法內傳遞fair=true,則返回的是公平鎖,默認是非公平鎖,關鍵字synchronized也是非公平鎖。 ``` ReentrantLock lock = new ReentrantLock(true); ``` 公平鎖會按鎖的線程等待隊列的順序,公平的讓線程獲取到鎖,所以性能會比非公平鎖低。 ## 等待隊列 Condition `Condition`是重入鎖的好搭檔,讓鎖可以支持多個等待隊列。提供了和`Object.wait()`、`Object.notify()`和對應功能的方法`Condition.await()`、`Condition.signal()`和`Condition.signalAll()` ![](https://img.kancloud.cn/20/41/2041554d2202bcbb68945cc57249bbcf_1500x1370.png) 具體使用可參考`ArrayBlockQueue`的實現。 ## 信號量 Semaphore 無論是內部鎖synchronized還是重入鎖ReentrantLock,一次都只允許一個線程訪問臨界區資源。而 `Semaphore`可以同時允許多個線程同時訪問某一個資源。 構造方法如下: ~~~ public Semaphore(int permits);// 第一個參數信號量數量 public Semaphore(int permits, boolean fair); // 第二個參數是否公平 ~~~ 主要方法如下: ``` public void acquire(); // 獲取許可,阻塞直到獲取到或者線程被中斷 public void acquireUninterruptibly(); // 獲取許可,阻塞直到獲取到,不響應中斷 public boolean tryAcquire(); // 嘗試獲取許可,直接返回結果 public boolean tryAcquire(long timeout,TimeUnit unit); // 在限定時間內嘗試獲取許可 public void release(); // 釋放許可 ``` 是一個有效的流量控制工具,它基于AQS共享鎖實現。常常用它來控制對有限資源的訪問。 * 每次使用資源前,先申請一個信號量,如果資源數不夠,就會阻塞等待; * 每次釋放資源后,就釋放一個信號量。 ## 讀寫鎖 ReadWriteLock 讀寫分離鎖可以減少鎖競爭,提升性能,適合在讀多寫少的場景使用。 是JDK5中提供的,實現類有`ReentrantReadWriteLock`。 ![](https://img.kancloud.cn/f9/ea/f9eae7869b0e10d51cf6a6a5cc2302f1_868x194.png) ~~~ ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); Lock readLock = readWriteLock.readLock();// 讀鎖,共享鎖 Lock writeLock = readWriteLock.writeLock();// 寫鎖,獨占鎖 ~~~ ## 倒計數器 CountDownLatch CountDownLatch是一個非常實用的多線程控制工具類,可以讓某一個線程等待,直到倒計數器結束。典型的場景,如火箭發射時的倒數計時(等待各個發射細節就位)。 ![](https://img.kancloud.cn/a5/b2/a5b2ec6af880f3d9d782e5bb375b3310_1410x802.png) ~~~ CountDownLatch countDownLatch = new CountDownLatch(3); // 注意:相關檢查是多線程并發執行的 // 檢查1 // doCheck1() countDownLatch.countDown(); // 檢查2 // doCheck2() countDownLatch.countDown(); // 檢查3 // doCheck3() countDownLatch.countDown(); // 等待檢查完成,再執行發射邏輯 countDownLatch.await(); // 點火發射 // doFire() ~~~ ## 循環柵欄 CyclicBarrier `CyclicBarrier`也是一種多線程并發控制的工具,和`CountDownLatch`類似,前者可以重復使用,而后者只使用一次。 ![](https://img.kancloud.cn/47/95/47950322eb7f4195acbb402767a21640_1648x858.png) 例子: ~~~ public static void main(String[] args) { CyclicBarrier cyclicBarrier1 = new CyclicBarrier(2, () -> { System.out.println("滿2個,group1執行完了"); }); CyclicBarrier cyclicBarrier2 = new CyclicBarrier(3, () -> { System.out.println("滿3個,group2執行完了"); }); for(int i=0;i<100;i++) { boolean b = i % 2 == 0; Thread t1 = new Thread(() -> { try { if(b){ // 偶數,則到籬笆1 cyclicBarrier1.await(); }else{ // 偶數,則到籬笆2 cyclicBarrier2.await(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "跑完了"); }); t1.setName("t"+i); t1.start(); } } ~~~ 輸出: ``` 滿2個,group1執行完了 t2跑完了 t0跑完了 滿3個,group2執行完了 t5跑完了 t1跑完了 t3跑完了 滿2個,group1執行完了 t6跑完了 t4跑完了 滿2個,group1執行完了 t10跑完了 t8跑完了 ``` ## 阻塞工具類 LockSupport `LockSupport`是一個非常方便使用的線程阻塞工具,可以在任意線程內讓線程阻塞,不需要先獲得某個對象的鎖,也不會拋出中斷異常。(底層實現類似信號量_counter計數,當park時,這個變量置為了0,當unpark時,這個變量置為1) ~~~ LockSupport.park(); // 阻塞當前線程,也有限時等待,還支持中斷響應 LockSupport.unpark(Thread.currentThread()); // 恢復某個線程 ~~~ ## 參考文檔 * 書籍:葛一鳴 *《Java高并發程序設計第二版》
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看