最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java并發(fā)Lock接口實(shí)現(xiàn)示例詳解

 更新時(shí)間:2023年06月22日 09:07:23   作者:右耳菌  
這篇文章主要為大家介紹了Java并發(fā)Lock接口,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Locks包 類層次結(jié)構(gòu)

Lock接口

方法簽名描述說明
void lock();獲取鎖(不死不休)一直獲取鎖,直到拿到為止
boolean tryLock();獲取鎖(淺嘗輒止)嘗試獲得鎖,獲取不到就算了
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;獲取鎖(過時(shí)不候)超時(shí)限制,超過時(shí)間就放棄
void lockInterruptibly() throws InterruptedException;獲取鎖(任人擺布)可以在外部通過方法中斷
void unlock();釋放鎖
Condition newCondition();

結(jié)論:

1、lock()最常用;

2、lockInterruptibly()方法一般更昂貴,有的impl可能沒有實(shí)現(xiàn)lockInterruptibly(),只有真的需要效應(yīng)中斷時(shí),才使用,使用之前看看impl對(duì)該方法的描述。

trylock

package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class GetLock_Demo {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        lock.lock(); //主線程拿到鎖
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                boolean rs = lock.tryLock();
                System.out.println("是否獲取到鎖: " + rs);
            }
        });
        th.start();
        Thread.sleep(2000L);
        th.interrupt();//中斷線程運(yùn)行
        System.out.println("th 線程被中斷了");
    }
}

是否獲取到鎖: false
th 線程被中斷了

  • trylock帶超時(shí)
package lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class GetLock_Demo {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        lock.lock(); //主線程拿到鎖
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                boolean rs = false;
                try {
                    rs = lock.tryLock(1, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("是否獲取到鎖: " + rs);
            }
        });
        th.start();
        Thread.sleep(2000L);
        th.interrupt();//中斷線程運(yùn)行
        System.out.println("th 線程被中斷了");
    }
}

是否獲取到鎖: false
th 線程被中斷了

lockInterruptibly

package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class GetLock_Demo {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        lock.lock(); //主線程拿到鎖
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lock.lockInterruptibly();
                } catch (InterruptedException e) {
                    System.out.println("獲取鎖時(shí)被中斷了");
                    e.printStackTrace();
                }
            }
        });
        th.start();
        Thread.sleep(2000L);
        th.interrupt();//中斷線程運(yùn)行
        System.out.println("th 線程被中斷了");
    }
}

 th 線程被中斷了
獲取鎖時(shí)被中斷了
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
    at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
    at lock.GetLock_Demo$1.run(GetLock_Demo.java:16)
    at java.lang.Thread.run(Thread.java:748)

lock and unlock

package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class GetLock_Demo {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        lock.lock(); //主線程拿到鎖
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("嘗試獲得鎖");
                lock.lock();
                System.out.println("獲得鎖了");
            }
        });
        th.start();
        Thread.sleep(2000L);
        th.interrupt();//中斷線程運(yùn)行
        System.out.println("th 線程被中斷了");
        Thread.sleep(5000L);
        lock.unlock();
    }
}

嘗試獲得鎖
th 線程被中斷了
獲得鎖了

Condition

Condition 一般是將其中的await和signal成對(duì)使用的,且一般是await在前signal在后,而且調(diào)用的使用,應(yīng)該確保本身是獲取到鎖的情況下,不然會(huì)出現(xiàn)以下問題:

1. await 和 signal 方法應(yīng)該在lock內(nèi)部調(diào)用,否則會(huì)發(fā)生 IllegalMonitorStateException 異常

package lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Condition_Demo {
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "獲得鎖");
                    condition.await(); //因?yàn)檫@里將線程掛起,所以后面無法執(zhí)行
                    System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "開始執(zhí)行~");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        thread.start();
        Thread.sleep(2000L);
        System.out.println("休眠2s,來控制線程");
        condition.signal(); //直接喚醒會(huì)報(bào)錯(cuò),因?yàn)閘ock方法執(zhí)行在Thread-0線程內(nèi)部,而我們代碼在這里執(zhí)行的是main線程,所以會(huì)報(bào)錯(cuò),
    }
}

 當(dāng)前線程:Thread-0獲得鎖
休眠2s,來控制線程
Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1939)
    at lock.Condition_Demo.main(Condition_Demo.java:33)

2. signal應(yīng)該在await后調(diào)用,否則會(huì)導(dǎo)致死鎖

package lock;
import sync.ReentrantLockDemo;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Condition_Demo {
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000L);
                    System.out.println("休眠3秒,等待主線程先執(zhí)行.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.lock();
                try {
                    System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "獲得鎖");
                    condition.await(); //因?yàn)檫@里將線程掛起,所以后面無法執(zhí)行
                    System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "開始執(zhí)行~");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        };
        thread.start();
        Thread.sleep(2000L);
        System.out.println("休眠2s,來控制線程");
        lock.lock();
        condition.signal(); //直接喚醒會(huì)報(bào)錯(cuò),因?yàn)閘ock方法執(zhí)行在Thread-0線程內(nèi)部,而我們代碼在這里執(zhí)行的是main線程,所以會(huì)報(bào)錯(cuò),
        lock.unlock(); //獲取到了這把鎖,然后解鎖.
        //2.當(dāng)然這里會(huì)出現(xiàn)死鎖的,如果signal方法在我們的await之前執(zhí)行,那么這里就會(huì)死鎖
    }
}

休眠2s,來控制線程
休眠3秒,等待主線程先執(zhí)行.
當(dāng)前線程:Thread-0獲得鎖
// 這里死鎖了

  • 使用condition實(shí)現(xiàn)阻塞隊(duì)列的例子
package lock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BlockingQueue_Demo {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue kaneBlockingQueue = new BlockingQueue(6);
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                    kaneBlockingQueue.put("x" + i);
                }
            }
        }.start();
        Thread.sleep(1000L);
        System.out.println("開始取元素");
        for (int i = 0; i < 8; i++) {
            kaneBlockingQueue.take();
            Thread.sleep(2000);
        }
    }
}
class BlockingQueue {
    List<Object> list = new ArrayList<>();
    private Lock lock = new ReentrantLock();
    private Condition putCondition = lock.newCondition(); //condition可以有多個(gè),針對(duì)不同的操作放入不同condition,相當(dāng)于等待隊(duì)列
    private Condition takeCondition = lock.newCondition();
    private int length;
    public BlockingQueue(int length) {
        this.length = length;
    }
    public void put(Object obj) {
        lock.lock(); //思考一個(gè)讀一個(gè)寫,為什么要加鎖呢?
        try {
            while (true) {
                if (list.size() < length) { //我們集合的長度不能超過規(guī)定的長度,才能向里面放東西
                    list.add(obj);
                    System.out.println("隊(duì)列中放入元素:" + obj);
                    takeCondition.signal();
                    return;
                } else { //如果放不進(jìn)去,就該阻塞. --利用condition實(shí)現(xiàn)
                    putCondition.await();//掛起
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public Object take() {
        lock.lock();
        try {
            while (true) {
                if (list.size() > 0) {
                    Object obj = list.remove(0);
                    System.out.println("隊(duì)列中取得元素:" + obj);
                    putCondition.signal();
                    return obj;
                } else {
                    takeCondition.await();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            return null;
        }
    }
}

隊(duì)列中放入元素:x0
隊(duì)列中放入元素:x1
隊(duì)列中放入元素:x2
隊(duì)列中放入元素:x3
隊(duì)列中放入元素:x4
隊(duì)列中放入元素:x5
開始取元素
隊(duì)列中取得元素:x0
隊(duì)列中放入元素:x6
隊(duì)列中取得元素:x1
隊(duì)列中放入元素:x7
隊(duì)列中取得元素:x2
隊(duì)列中放入元素:x8
隊(duì)列中取得元素:x3
隊(duì)列中放入元素:x9
隊(duì)列中取得元素:x4
隊(duì)列中取得元素:x5
隊(duì)列中取得元素:x6
隊(duì)列中取得元素:x7

Process finished with exit code 0

可重入鎖 ReentrantLock

一般來說,如果可重入鎖的加鎖次數(shù)是n,那么解鎖次數(shù)也得是n才能完全釋放鎖,否則,如果小于n 則無法正常釋放鎖,此時(shí)如果有別的線程要加鎖,則無法獲取到鎖而被阻塞;如果大于n,則會(huì)觸發(fā) IllegalMonitorStateException 異常, ReentrantLock 默認(rèn)是使用非公平鎖,如果要使用公平鎖,可以使用 new ReentrantLock(true) 來創(chuàng)建。

  • 小于n的情況
package lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Reentrant_Demo {
    static Lock lock = new ReentrantLock();
    public static void main(String[] args) {
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "獲得第1次鎖");
        lock.lock();
        System.out.println(Thread.currentThread().getName() + "獲得第2次鎖");
        lock.unlock();
        new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "開始去釋放鎖");
                lock.lock();
                System.out.println("獲得鎖成功~~~");
                lock.unlock();
            }
        }.start();
    }
}
main獲得第1次鎖
main獲得第2次鎖
Thread-0開始去釋放鎖
// 子線程獲取鎖失敗導(dǎo)致阻塞了
  • 大于n的情況修改成3次unlock
        // 修改成3次unlock
        lock.unlock();
        lock.unlock();
        lock.unlock();
main獲得第1次鎖
main獲得第2次鎖
Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    at lock.Reentrant_Demo.main(Reentrant_Demo.java:18)

簡單說明圖

實(shí)現(xiàn)一個(gè)ReenrantLock的demo版本 - 一個(gè)現(xiàn)實(shí)思想的簡單版本

package lock;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
public class ReentrantLock_Demo implements Lock {
    //記錄鎖的擁有者
    AtomicReference<Thread> owner = new AtomicReference<>();
    //記錄重入次數(shù)的count
    AtomicInteger count = new AtomicInteger(0);
    //等待隊(duì)列
    private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue();
    @Override
    public boolean tryLock() {
        //判斷count值是否為0,如果count不等于0,說明鎖被占用
        int ct = count.get();
        //判斷鎖是不是自己占用的,做重入
        if (ct != 0) {
            if (Thread.currentThread() == owner.get()) {
                count.set(ct + 1);
                return true;
            }
        } else { //若count為0 ,表示當(dāng)前鎖未被占用,通過CAS操作
            if (count.compareAndSet(ct, ct + 1)) {
                owner.set(Thread.currentThread());          //如果不是自己,進(jìn)入隊(duì)列
                return true;
            }
        }
        return false;
    }
    @Override
    public void lock() {
        if (!tryLock()) {
            //加入等待隊(duì)列
            waiters.offer(Thread.currentThread());
            while (true) {
                //若線程是隊(duì)列頭部,先判斷一次,現(xiàn)在能不能去搶,然后再去加鎖
                Thread head = waiters.peek();
                if (head == Thread.currentThread()) {
                    if (!tryLock()) {
                        LockSupport.park();
                    } else {
                        waiters.poll();
                        return;
                    }
                } else {
                    LockSupport.park();
                }
            }
        }
    }
    public boolean tryUnlock() {
        if (owner.get() != Thread.currentThread()) {
            throw new IllegalMonitorStateException();
        } else {
            int ct = count.get();
            int nextc = ct - 1;
            count.set(nextc);
            if (nextc == 0) { //可重入鎖被加鎖多次,一旦為0 就釋放鎖,如果不是0,還得繼續(xù)釋放
                owner.compareAndSet(Thread.currentThread(), null);
                return true;
            } else {
                return false;
            }
        }
    }
    @Override
    public void unlock() {
        if (tryUnlock()) {
            Thread head = waiters.peek();
            if (head != null) {
                LockSupport.unpark(head);
            }
        }
    }
    /**
     * 暫時(shí)忽略
     *
     * @throws InterruptedException
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
    }
    /**
     * 暫時(shí)忽略
     *
     * @throws InterruptedException
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }
    /**
     * 暫時(shí)忽略
     *
     * @throws InterruptedException
     */
    @Override
    public Condition newCondition() {
        return null;
    }
}

以上就是Java并發(fā)Lock接口實(shí)現(xiàn)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java并發(fā)Lock接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于SpringBoot和Vue3的博客平臺(tái)文章列表與分頁功能實(shí)現(xiàn)

    基于SpringBoot和Vue3的博客平臺(tái)文章列表與分頁功能實(shí)現(xiàn)

    在前面的教程中,我們已經(jīng)實(shí)現(xiàn)了基于Spring Boot和Vue3的發(fā)布、編輯、刪除文章功能。本教程將繼續(xù)引導(dǎo)您實(shí)現(xiàn)博客平臺(tái)的文章列表與分頁功能,需要的朋友可以參考閱讀
    2023-04-04
  • Java數(shù)據(jù)結(jié)構(gòu)最清晰圖解二叉樹前 中 后序遍歷

    Java數(shù)據(jù)結(jié)構(gòu)最清晰圖解二叉樹前 中 后序遍歷

    樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點(diǎn))按分支關(guān)系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會(huì)的族譜和各種社會(huì)組織機(jī)構(gòu)都可用樹形象表示
    2022-01-01
  • rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼)

    rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼)

    這篇文章主要介紹了rabbitmq五種模式詳解(含實(shí)現(xiàn)代碼),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • SpringBoot3使用Swagger3的示例詳解

    SpringBoot3使用Swagger3的示例詳解

    本文介紹了如何在Spring Boot 3項(xiàng)目中使用Swagger3進(jìn)行后端接口的前端展示,首先,通過添加依賴并配置application.yml文件來快速啟動(dòng)Swagger,然后,詳細(xì)介紹了Swagger3的新注解與Swagger2的區(qū)別,并提供了一些常用注解的使用示例,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • java檢查服務(wù)器的連通兩種方法代碼分享

    java檢查服務(wù)器的連通兩種方法代碼分享

    這篇文章主要介紹了java檢查服務(wù)器的連通兩種方法代碼分享,涉及ping的介紹以及檢查服務(wù)器連通的兩種方法代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Spring中自動(dòng)注入的兩種方式總結(jié)

    Spring中自動(dòng)注入的兩種方式總結(jié)

    Spring的核心技術(shù)IOC(Intorol of Converse控制反轉(zhuǎn))的實(shí)現(xiàn)途徑是DI(dependency Insert依賴注入)。而依賴注入(DI)的實(shí)現(xiàn)方式又有兩種,xml方式和注解方式。本文就來詳細(xì)聊聊這兩個(gè)方式,需要的可以了解一下
    2022-10-10
  • 使用Spring中的scope配置和@scope注解

    使用Spring中的scope配置和@scope注解

    這篇文章主要介紹了使用Spring中的scope配置和@scope注解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java實(shí)現(xiàn)的求逆矩陣算法示例

    Java實(shí)現(xiàn)的求逆矩陣算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的求逆矩陣算法,涉及java基于數(shù)組的矩陣遍歷與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • Intellij IDEA如何去掉@Autowired 注入警告的方法

    Intellij IDEA如何去掉@Autowired 注入警告的方法

    這篇文章主要介紹了Intellij IDEA如何去掉@Autowired 注入警告的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • SpringBoot中WebClient的實(shí)踐過程

    SpringBoot中WebClient的實(shí)踐過程

    本文介紹了SpringBoot中WebClient的使用,包括配置、使用場(chǎng)景以及優(yōu)化策略,幫助開發(fā)者更高效地進(jìn)行服務(wù)間通信,WebClient具有非阻塞式I/O、強(qiáng)大的功能、靈活性等優(yōu)點(diǎn),適用于高并發(fā)場(chǎng)景,通過合理配置和優(yōu)化,可以顯著提升服務(wù)間通信的效率和可靠性
    2025-12-12

最新評(píng)論

广南县| 景宁| 贡嘎县| 北海市| 郁南县| 五华县| 紫金县| 内乡县| 天台县| 庆元县| 武城县| 沭阳县| 清苑县| 乡城县| 张家界市| 宁都县| 北京市| 淳化县| 岑巩县| 茌平县| 荃湾区| 昌邑市| 南郑县| 富裕县| 弥渡县| 长泰县| 车险| 若羌县| 清丰县| 延川县| 醴陵市| 舞钢市| 梁河县| 唐山市| 麻城市| 双柏县| 岳西县| 云南省| 佛教| 宁乡县| 锦屏县|