中断和超时
当线程使用LockSupport.park挂起的时候,可能是被中断或超时唤醒,而不是被另一个线程通过LockSupport.unpark唤醒,所以在线程被唤醒的时候判断是因为那一种情况唤醒,从而使用不同的处理方式
中断
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException(); //方法开头判断线程是否已经被中断
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) //判断挂起的线程是否被外部线程中断
throw new InterruptedException(); //1.对中断的处理是直接抛出中断异常
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//判断挂起的线程是否被外部线程中断
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this); //park方法可以被interupt
return Thread.interrupted(); //判断挂起的线程是否被外部线程中断,并清除中断标志
}
}
1.对中断的处理是直接抛出中断异常
超时
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implement java.io.Serializable {
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();//方法开头判断线程是否已经被中断
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;//计算超时时间
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null;
failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime(); //如果超时时间-当前时间<=0说明已经超时
if (nanosTimeout <= 0L)
return false; //2.对超时的处理是超时请求资源失败,并不会抛出异常
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout); //使用LockSupport.parkNanos挂起线程,超时就会唤醒,判断是否是因为超时导致线程被唤醒的
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
}
2.对超时的处理是超时请求资源失败,并不会抛出异常