Java线程饥饿详解
一、什么是线程饥饿?
线程饥饿是指某个线程因长期无法获得所需资源(如CPU时间、锁、I/O资源等)而无法正常执行的情况。就像食堂排队时有人永远被插队,始终吃不上饭。
二、饥饿的三大原因
高优先级霸凌
若存在高优先级线程持续抢占资源:
Thread vipThread = new Thread(() -> {
while(true) { /* 长期占用CPU */ }
});
vipThread.setPriority(Thread.MAX_PRIORITY);
非公平锁陷阱
使用ReentrantLock非公平锁时:
Lock unfairLock = new ReentrantLock(); // 默认非公平
// 后来的线程可能比先到的线程先拿到锁
资源分配失衡
类似公司打印机被市场部长期独占:
synchronized(printer) {
marketDept.print1000Pages(); // 市场部打印耗时操作
}
三、真实场景案例
外卖平台派单系统故障
某平台使用固定大小线程池处理订单:
ExecutorService pool = Executors.newFixedThreadPool(4);
// 当第五个订单到达时,必须等待线程释放
导致新订单在高峰时段永远无法被处理,用户投诉暴增。
四、解决方案
公平锁正义卫士
Lock fairLock = new ReentrantLock(true); // 启用公平模式
优先级中庸之道
thread.setPriority(Thread.NORM_PRIORITY); // 慎用高低优先级
资源池动态扩容
使用newCachedThreadPool()替代固定线程池:
ExecutorService dynamicPool = Executors.newCachedThreadPool();
超时防御机制
if(lock.tryLock(3, TimeUnit.SECONDS)) {
// 成功获取锁
} else {
// 记录饥饿报警
}
五、思维导图
六、总结
线程饥饿如同交通堵塞中的"永远等不到的绿灯",通过公平机制、弹性资源分配、超时控制三管齐下,可有效避免这类"慢性系统病"。