<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之旅 廣告
                # 如何實現一個自己的顯式鎖Lock 首先我們通過代碼引出一個問題:如果方法上了同步鎖并且被一個線程占有了,那么其他線程想執行這個方法就要一直等待下去,如果這個方法死循環或者無限執行下去,等待的線程就會無限等待下去,這里來演示一下這種場景: ```java /** * @program: ThreadDemo * @description: synchronized機制導致的一個問題:synchronized不能被打斷,導致其他線程搶不到鎖。 * @author: hs96.cn@Gmail.com * @create: 2020-09-14 */ public class SynchronizedProblem { public static void main(String[] args) { new Thread(SynchronizedProblem::run, "T1").start(); new Thread(SynchronizedProblem::run, "T2").start(); } private synchronized static void run() { System.out.println(Thread.currentThread().getName()); while (true) { //一直執行下去。。。 } } } ``` 運行效果如下: ![](https://img.kancloud.cn/f6/7c/f67c5c9821d633e66bd097a4003ba80c_1154x227.gif) 使用interrupt()打斷一下T2線程: ```java public class SynchronizedProblem { public static void main(String[] args) throws InterruptedException { new Thread(SynchronizedProblem::run, "T1").start(); Thread.sleep(1000); Thread t2 = new Thread(SynchronizedProblem::run, "T2"); t2.start(); Thread.sleep(2000); t2.interrupt(); System.out.println(t2.isInterrupted());// true,但是并沒有打斷t2 } private synchronized static void run() { System.out.println(Thread.currentThread().getName()); while (true) { //一直執行下去 } } } ``` 運行效果如下: ![](https://img.kancloud.cn/0e/87/0e87ccd3662a5e1594b5b2a7a13f5acd_1154x227.gif) 因為同步方法里有while循環,接收不到中斷異常的,所以基于這個場景我們來定義一個帶有超時功能的鎖,思路還是和上一個案例差不多,一個while一直檢測lock,再結合wait(),notifyAll(),代碼如下: 我們先定義一個Lock interface: ```java package com.thread.thread20; import java.util.Collection; public interface Lock { class TimeOutException extends Exception { public TimeOutException(String message) { super(message); } } /** * 加鎖 * * @throws InterruptedException 打斷異常 */ void lock() throws InterruptedException; /** * 加鎖 * * @param mills 加鎖時間 * @throws InterruptedException 打斷異常 * @throws TimeOutException 超時異常 */ void lock(long mills) throws InterruptedException, TimeOutException; /** * 解鎖 */ void unlock(); /** * 獲取爭搶鎖時被阻塞的線程 * * @return 被阻塞線程的集合 */ Collection<Thread> getBlockedThread(); /** * 獲取爭搶鎖時被阻塞的線程的數量 * * @return 被阻塞的線程的數量 */ int getBlockedSize(); } ``` 定義一個類來實現接口: ```java package com.thread.thread20; import java.util.Collection; /** * @program: ThreadDemo * @description: 自定義顯式鎖 Boolean Lock * @author: hs96.cn@Gmail.com * @create: 2020-09-14 */ public class BooleanLock implements Lock { @Override public void lock() throws InterruptedException { } @Override public void lock(long mills) throws InterruptedException, TimeOutException { } @Override public void unlock() { } @Override public Collection<Thread> getBlockedThread() { return null; } @Override public int getBlockedSize() { return 0; } } ``` 我們來定義兩個成員變量: `initValue`為`true`代表正在被占用,`false`反之。 `blockedThreadCollection`來存放阻塞的線程。 ```java private boolean initValue; private Collection<Thread> blockedThreadCollection = new ArrayList<>(); public BooleanLock() { this.initValue = true; } ``` 完善lock方法: ```java @Override public synchronized void lock() throws InterruptedException { // 鎖已經被其他線程使用 while (initValue) { blockedThreadCollection.add(Thread.currentThread()); this.wait(); } // 鎖未被使用,搶到鎖立即設置initValue的值 this.initValue = true; blockedThreadCollection.remove(Thread.currentThread()); } ``` 這里和上一篇的數據采集很相似。 完善unlock方法: ```java @Override public void unlock() { this.initValue = false; Optional.of(Thread.currentThread().getName() + " release the lock monitor.").ifPresent(System.out::println); this.notifyAll(); } ``` 查詢方法完善如下: ```java @Override public Collection<Thread> getBlockedThread() { return Collections.unmodifiableCollection(blockedThreadCollection); } @Override public int getBlockedSize() { return blockedThreadCollection.size(); } ``` `return`的`Collections`一定使用`unmodifiableCollection`因為直接返回的是一個實例,調用者可以隨意更改。所以我們把他置為·`unmodifiableCollection`。 測試一下代碼: ```java package com.thread.thread20; import java.util.Optional; import java.util.stream.Stream; /** * @program: ThreadDemo * @description: 用來調用我們自己寫的顯示Lock * @author: hs96.cn@Gmail.com * @create: 2020-09-14 */ public class LockTest { public static void main(String[] args){ final BooleanLock booleanLock = new BooleanLock(); Stream.of("T1", "T2", "T3", "T4").forEach(name -> { new Thread(() -> { try { booleanLock.lock(); Optional.of(Thread.currentThread().getName() + " have the lock Monitor.").ifPresent(System.out::println); work(); } catch (InterruptedException e) { e.printStackTrace(); } finally { booleanLock.unlock(); } }, name).start(); }); } private static void work() throws InterruptedException { Optional.of(Thread.currentThread().getName() + " is working...").ifPresent(System.out::println); Thread.sleep(2_000); } } ``` 運行效果如下: ![](https://img.kancloud.cn/60/f1/60f16f4413126be637a00455cae41d5e_1154x227.gif) 可以看到報錯了,這里為了印象深刻一下,特意留了個彩蛋,其實上面的代碼里我也故意留了彩蛋~~。`notifyAll`需要一個`monitor`才可以,我們把`synchronized`加上運行效果如下: ![](https://img.kancloud.cn/3f/64/3f6430ffd6fe63830d5c807b67310873_1154x227.gif) 嗯到這里大體效果實現了,但是細想還是有問題的,如果要你編寫一個這個方法的測試用例,你會怎么寫呢? unlock()沒做任何限制,我們的測試類是可以隨意調用的: ```java try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } booleanLock.unlock(); ``` 運行效果如下: ![](https://img.kancloud.cn/c9/d1/c9d16cebcfcefde2769afc214d2baa8c_1082x227.gif) T1線程還工作,T4直接就搶到鎖了,那么我們在這個基礎上再做一層校驗: ```java private Thread currentThread; //增加一個currentThread代表當前拿到線程的鎖 ``` ```java currentThread = Thread.currentThread(); ``` ```java @Override public synchronized void unlock() { // 釋放鎖 if (Thread.currentThread() == currentThread) { this.initValue = false; Optional.of(Thread.currentThread().getName() + " release the lock monitor.").ifPresent(System.out::println); this.notifyAll(); } } ``` 再運行一下: ![](https://img.kancloud.cn/6d/77/6d77ba5298a0d85be3e5dc422e850f11_1082x227.gif) 以這個為主體,增加時間限制來完善我們的Lock: ```java public static void main(String[] args) throws InterruptedException { final BooleanLock booleanLock = new BooleanLock(); Stream.of("T1", "T2", "T3", "T4").forEach(name -> { new Thread(() -> { try { booleanLock.lock(2000L); Optional.of(Thread.currentThread().getName() + " have the lock Monitor.").ifPresent(System.out::println); work(); } catch (InterruptedException e) { e.printStackTrace(); } catch (Lock.TimeOutException e) { Optional.of(Thread.currentThread().getName() + " time out.").ifPresent(System.out::println); } finally { booleanLock.unlock(); } }, name).start(); }); } ``` ```java private static void work() throws InterruptedException { Optional.of(Thread.currentThread().getName() + " is working...").ifPresent(System.out::println); Thread.sleep(5_000); } ``` ```java @Override public void lock(long mills) throws InterruptedException, TimeOutException { if (mills <= 0) { lock(); } long hasRemaining = mills; long endTime = System.currentTimeMillis() + mills; while (initValue) { if (hasRemaining <= 0) { throw new TimeOutException("Time Out"); } blockedThreadCollection.add(Thread.currentThread()); this.wait(mills); hasRemaining = endTime - System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + ">>" + hasRemaining); } this.initValue = true; this.currentThread = Thread.currentThread(); } ``` 運行效果如下: ![](https://img.kancloud.cn/3b/9d/3b9d9377dcb7787908e232af4139e312_1082x227.gif) T1線程進來搶到鎖,但是需要5秒才能運行結束,其他線程最多等待2秒,所以其他線程先結束等待超時了,T1才釋放鎖。這個顯式鎖就先到這,上面代碼我故意貼了一些錯誤的,不知道細心的朋友有沒有發現=.=
                  <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>

                              哎呀哎呀视频在线观看