2026年1月17日大约 17 分钟
- C++24
- Rust8
- WSL6
- hdoj5
- Java4
- 虚拟机2
- AI Security2
- Compiler Principle1
- eNSP1
- Git1
- RabbitMQ1
- Linux1
- Nodejs1
- VSCode1
- yapi1
- C1
- MySQL1
问题分析
今天偶然看到一道死锁分析的题,代码如下:
package com.github.ixanadu13;
import org.junit.jupiter.api.Test;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ExecutorTest {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
class LocalTFileTask implements Callable<String> {
@Override
public String call() throws Exception {
return "";
}
}
class RenderPageTask implements Callable<String> {
@Override
public String call() throws Exception {
final Future<String> f1 = executor.submit(new LocalTFileTask());
final Future<String> f2 = executor.submit(new LocalTFileTask());
return f1.get() + f2.get();
}
}
public void renderPage() throws Exception{
Future<String> page = executor.submit(new RenderPageTask());
page.get();
}
@Test
public void test() throws Exception {
var test = new ExecutorTest();
test.renderPage();
}
}
2025年8月6日大约 3 分钟
| Thread#sleep | Object#wait | LockSupport#park | |
|---|---|---|---|
| 调用方式 | 抛出中断异常 | 必须在synchronized块中、抛出中断异常。如果当前线程不是对象锁的拥有者,调用wait/notify会抛出 IllegalMonitorStateException 异常 | 无限制,无抛出 |
| 阻塞时是否释放当前线程占有的锁 | 不释放 | 释放 | 不释放 |
| 传入参数 | 必须传入时间 | 可选传入超时时间 | 可选传入超时时间、阻塞原因blocker |
| 唤醒方式 | 无法从外部唤醒 | Object#notify,还需抢锁成功。wait前调用notify无效 | LockSupport#unpark,唤醒传入的执行线程。park前调用unpark有效 |
| 中断响应 | 抛出中断异常,清除中断标志位 | 抛出中断异常,清除中断标志位 | park方法返回,不抛异常,中断响应位依然为true |
| 底层实现 | native方法Thread#sleep0 | native方法Object#wait0 | 调用Unsafe#park。类似只有一个许可证的Semaphore,且重复执行最多获得一个许可证 |
2025年4月28日小于 1 分钟
主要日志系统
JUL
Java标准库java.util.logging,但不常用。
Log4j
Log4j 的短板在于性能,在Logback 和 Log4j2 出来之后,Log4j的使用也减少了。
Logback
同样由Log4j的作者开发,提供了性能更好的实现,异步 logger,Filter等更多的特性。
Log4j2
由Log4j维护者开发,诞生晚于logback,因此吸收了slf4j和logback的一些优点(比如日志模板),性能也比较好。在设计上分离Facade和Implementation,即log4j-api和 log4j-core。
2025年1月26日大约 2 分钟