java线程/方法超时控制(2)-从CountDownLatch await细节开始

    纯记录,记忆越来越差,能力又一般,纯讨论简单细节。线程超时控制的方法有很多也有很多新的方法,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)) {
   // 超时啦,打个日志?做个处理?
}

 

 

你可能感兴趣的:(java线程/方法超时控制(2)-从CountDownLatch await细节开始)