Java并发与面试-每日必看(14)

前言

Java不秃,面试不慌!
欢迎来到这片 Java修炼场!这里没有枯燥的教科书,只有每日一更的 硬核知识+幽默吐槽,让你在欢笑中掌握 Java基础、算法、面试套路,摆脱“写代码如写诗、看代码如看天书”的困境。
记住: 代码会背叛你,但知识不会! 坚持积累,总有一天,HR会为你的八股文落泪,面试官会因你的算法沉默。


ReentrantLock中tryLock()和lock()⽅法的区别

想象一下,你和朋友去奶茶店买奶茶,但店里有一台超级慢的奶茶机,只能一次给一个人做奶茶。你们俩都想喝,那该怎么办?这时候就有两种策略——tryLock()lock()

tryLock() —— “碰碰运气”(非阻塞)

这个方法就像你走到奶茶店门口,发现有人排队,你心里嘀咕:“要不试试看,看能不能直接买到?”然后你探头一看,如果奶茶机正空着,你就立刻冲进去点单(获取锁)。如果发现前面有人在慢悠悠地搅拌珍珠,你就耸耸肩走开(拿不到锁,直接返回 false)。

ReentrantLock lock = new ReentrantLock();

if (lock.tryLock()) {  // 尝试获取锁
    try {
        System.out.println("耶!奶茶机空着,成功开冲!");
    } finally {
        lock.unlock();  // 用完要释放
    }
} else {
    System.out.println("唉,奶茶机有人用呢,算了,我先去别的地方逛逛。");
}

lock() —— “死磕到底”(阻塞型)

这个方法就像你一进奶茶店,发现奶茶机有人用,但你不管,认定今天一定要喝到奶茶。于是你二话不说,站在原地死等,不管前面的人是五分钟做完还是五十分钟,你都不会走,直到轮到你为止(获取锁)。

lock.lock();  // 阻塞式获取锁
try {
    System.out.println("我排定了,等多久都要喝到这杯奶茶!");
} finally {
    lock.unlock();
}

CountDownLatch和Semaphore的区别和底层原理

想象一下,你和一群朋友去游乐园玩,结果发现人太多,排队系统简直是门玄学。游乐园为了管理人流,采用了两种方式——CountDownLatch(倒计时门)Semaphore(限流闸机)。咱们一起来看看它们是怎么工作的!

🎯 CountDownLatch ——“等人齐了才能出发”

CountDownLatch 就像一个集体行动的出发门,大家约好了,必须等人全到了才能出发。比如,你和五个朋友相约坐过山车,工作人员说:“人齐了才能开!” 这时候,你坐在车上,等着队友们陆续到位(线程数不满足则阻塞)。

每当一个朋友到达,他们就会告诉工作人员:“我来了!”(countDown()),直到所有人都到齐,工作人员才打开闸门(await() 解除阻塞)。

CountDownLatch的await()将会阻塞,其他线程可以调⽤CountDownLatch的countDown()⽅法来对
CountDownLatch中的数字减⼀,当数字被减成0后,所有await的线程都将被唤醒。
import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3); // 需要等 3 个人到齐

        new Thread(() -> {
            System.out.println("🚗 朋友 A 抵达...");
            latch.countDown(); // A 抵达,人数 -1
        }).start();

        new Thread(() -> {
            System.out.println("🚗 朋友 B 抵达...");
            latch.countDown(); // B 抵达,人数 -1
        }).start();

        new Thread(() -> {
            System.out.println("🚗 朋友 C 抵达...");
            latch.countDown(); // C 抵达,人数 -1
        }).start();

        System.out.println("🎢 过山车等待所有人到齐...");
        latch.await(); // 阻塞,等 3 个人都到齐
        System.out.println("✅ 人齐了,出发!");
    }
}

底层原理

  • await():所有线程排队(AQS队列),等数字归零再放行。
  • countDown():每次减一,直到归零,才放行所有 await() 线程。

🚦 Semaphore ——“限流闸机,过多就等”

Semaphore 就像游乐园的限流闸机,一次最多允许 N 个人进入。比如碰碰车场地只能同时容纳 3 个人,每次一个人想玩,得刷个票(acquire()),如果车位满了,就得排队等别人玩完再释放车位(release())。

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); // 只允许 3 个人同时玩

        for (int i = 1; i <= 5; i++) { // 5 个人想玩
            final int person = i;
            new Thread(() -> {
                try {
                    System.out.println("👤 朋友 " + person + " 想玩碰碰车...");
                    semaphore.acquire(); // 尝试获取许可
                    System.out.println("🚗 朋友 " + person + " 开始玩了!");
                    Thread.sleep(2000); // 模拟玩游戏
                    System.out.println("🏁 朋友 " + person + " 玩完了,离开!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release(); // 释放许可
                }
            }).start();
        }
    }
}

底层原理

  • acquire():想获取许可证,如果没有可用的,就排队(AQS队列)。
  • release():释放许可证,通知排队的线程,让它们逐个进来。

🔍 总结

机制类比场景主要方法作用
CountDownLatch等人齐了才开车await() / countDown()一次性事件,倒计时归零后,所有等待的线程解除阻塞
Semaphore游乐园限流acquire() / release()控制同时有多少个线程访问资源,超过的线程必须等待

最后的话

  好了,今天的分享就到这里啦!写这篇文章,我可是连宵夜都没顾上吃(其实是吃太饱躺着写的)。如果你觉得这篇内容有点意思,那就点个 ,顺手 关注 一下吧!你的支持就是我继续码字的最大动力!💪🎉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry-Walker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值