这里所说的死锁检测并不是检索死锁,而是检测瓶颈
场景:在网络服务器中,网络任务很多,但是线程资源有限,不允许某个任务执行很长的时间,对任务的执行时间有上限要求,如上限设定为5秒钟。如果某任务的执行时间超过了上限时间,我们就认定线程有死锁的嫌疑,接下来的处理手段是终止线程,汇报线程正在执行快照,以及涉及的资源。
如下线程代码片段:
long endTime = System.currentTimeMillis() + timeoutMillis; //线程上限时间 timeoutMillis = 5 (s)
if (endTime < 0) {
endTime = Long.MAX_VALUE;
}
synchronized (lock) {
if (ready) {
return ready;
} else if (timeoutMillis <= 0) {
return ready; //线程正常执行
}
waiters++;
try {
for (;;) {
try {
long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL);
lock.wait(timeOut); //线程超时了.....
} catch (InterruptedException e) {
if (interruptable) { //超时,线程就该结束,可能有死锁,不管怎样,这个线程太费时间资源了
throw e;
}
}
if (ready) {
return true;
}
if (endTime < System.currentTimeMillis()) {
return ready;
}
}
} finally {
waiters--;
if (!ready) {
checkDeadLock(); //线程如果超时,才会执行“死锁检测”
}
}
}
上面的代码片段中,
1 如果超时,程序会抛出错误,线程结束,
2 finally 代码块会在程序抛出错误前执行 哈啊哈!执行耗时的资源此时都会在堆栈中
3 checkDeadLock()方法就能够检索线程执行的堆栈,从而汇报步骤和对象,帮助查找瓶颈所在
checkDeadLock()代码如下
private void checkDeadLock() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); //获取当前线程的堆栈信息
for (StackTraceElement s : stackTrace) {
System.out.println(s.getClassName()); //获取堆栈中对象的信息,这些信息将有助于排查瓶颈所在
}
}