前言
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() | 控制同时有多少个线程访问资源,超过的线程必须等待 |
最后的话
好了,今天的分享就到这里啦!写这篇文章,我可是连宵夜都没顾上吃(其实是吃太饱躺着写的)。如果你觉得这篇内容有点意思,那就点个 赞,顺手 关注 一下吧!你的支持就是我继续码字的最大动力!💪🎉