今天在看guava RateLimit源码的时候发现在操作线程sleep的时候写法和之前不一样,于是进去一探究竟。
@Override
void sleepMicrosUninterruptibly(long micros) {
if (micros > 0) {
Uninterruptibles.sleepUninterruptibly(micros, MICROSECONDS);
}
}
sleepUninterruptibly内部源码如下
public static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
boolean interrupted = false;
try {
// 将sleepFor转换为对应纳秒级别的数值
long remainingNanos = unit.toNanos(sleepFor);
long end = System.nanoTime() + remainingNanos;
while (true) {
try {
// TimeUnit.sleep() treats negative timeouts just like zero.
// sleep对应的纳秒时间
NANOSECONDS.sleep(remainingNanos);
return;
} catch (InterruptedException e) {
interrupted = true;
remainingNanos = end - System.nanoTime();
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
这里使用NANOSECONDS.sleep(remainingNanos)的写法代替sleep(xxxx)主要是更方便理解,将时间的单位显示表述出来。该改法同时也对sleep期间被中断的异常做了捕获,并计算出剩余需要sleep的时间,然后继续等待,直到耗尽所有时间。所以这个方法可以描述为不可中断的sleep。其意义是为了支持上层限流对于请求的控制。