纯记录,记忆越来越差,能力又一般,纯讨论简单细节。线程超时控制的方法有很多也有很多新的方法,CountDownLatch只是其中一种且不新,与CyclicBarrier不同的是 CountDownLatch一次性的,下面CountDownLatch的细节开始记录讨论一些东西。
看个例子,例子1很简单,起个线程,用CountDownLatch的带超时的 await方法控制超时
例子1:
CountDownLatch countDownLatch = new CountDownLatch(1);
TestThread testThread = new TitleThread(args, countDownLatch);
testThread.start();
try {
countDownLatch.await(countDownLatch, timeOut, TimeUnit.MILLISECONDS);
}catch (InterruptedException e) {
// 抓到一个中断异常
} catch (Exception e) {
// 抓到一个异常
}
await方法源码写的清楚,会抛出中断异常 InterruptedException,InterruptedException其实比较讨厌,在某些场景需要特别的留心和处理,好在这个例子里这么写显示调用线程不关心中断异常,笼统的捕获 Exception也没关系。此处不回抛出超时异常。
下面,换个写法
例子2:
import com.google.common.util.concurrent.Uninterruptibles
CountDownLatch countDownLatch = new CountDownLatch(1);
TestThread testThread = new TitleThread(args, countDownLatch);
testThread.start();
if (!Uninterruptibles.awaitUninterruptibly(countDownLatch, timeOut,TimeUnit.MILLISECONDS)){
// 超时啦,打个日志?做个处理?随你
}
看下 Uninterruptibles.awaitUninterruptibly 这个方法,看名字就是不许中断的等待方法,具体逻辑看源码
/**
* Invokes
* {@code latch.}{@link CountDownLatch#await(long, TimeUnit)
* await(timeout, unit)} uninterruptibly.
*/
@GwtIncompatible("concurrency")
public static boolean awaitUninterruptibly(CountDownLatch latch,
long timeout, TimeUnit unit) {
boolean interrupted = false;
try {
long remainingNanos = unit.toNanos(timeout);
long end = System.nanoTime() + remainingNanos;
while (true) {
try {
// CountDownLatch treats negative timeouts just like zero.
return latch.await(remainingNanos, NANOSECONDS);
} catch (InterruptedException e) {
interrupted = true;
remainingNanos = end - System.nanoTime();
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
内部还是调用await,多了一些包装,while里不断的尝试调用await,遇到中断了?不理,剩余时间改小,继续while循环,直到超时返回。当然最后在finally里重置了中断标志位,方便上层根据中断状态做点啥
CountDownLatch配合线程池使用也不错
executorService.submit(new TestTask(xx,xx,countDownLatch));
executorService.submit(new TestTask(xx,xx,countDownLatch));
executorService.submit(new TestTask(xx,xx,countDownLatch));
executorService.submit(new TestTask(xx,xx,countDownLatch));
// 阻塞住
if (!Uninterruptibles.awaitUninterruptibly(countDownLatch, timeOut, TimeUnit.MILLISECONDS)) {
// 超时啦,打个日志?做个处理?
}