今天看spring官方实例代码springboot整合rabbitmq发现有用到CountDownLatch
首先贴上spring demo
public class Receiver {
private CountDownLatch latch = new CountDownLatch(1);
public void receiveMessage(String message) {
System.out.println("Received <" + message + ">");
latch.countDown();
}
public CountDownLatch getLatch() {
return latch;
}
}
public class Runner implements CommandLineRunner {
private final RabbitTemplate rabbitTemplate;
private final Receiver receiver;
public Runner(Receiver receiver, RabbitTemplate rabbitTemplate) {
this.receiver = receiver;
this.rabbitTemplate = rabbitTemplate;
}
@Override
public void run(String... args) throws Exception {
System.out.println("Sending message...");
rabbitTemplate.convertAndSend(MqConfig.topicExchangeName, "foo.bar.baz", "Hello from RabbitMQ!");
receiver.getLatch().await(10000, TimeUnit.MILLISECONDS);
}
}
在这个demo中除了有参构造new CountDownLatch(1)
用到了CountDownLatch的两个方法latch.countDown()
和receiver.getLatch().await(10000, TimeUnit.MILLISECONDS)
让我们先看看官方文档https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
Modifier and Type | Method and Description |
---|---|
boolean | await(long timeout, TimeUnit unit) Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses. |
void | countDown() Decrements the count of the latch, releasing all waiting threads if the count reaches zero. |
看了文档可以知道countDown()每次回会让初始化的计数器减一。await用于阻塞当前线程直到计数器减到0,除非线程被打断或者等待超时。因此我们可以让初始计数为多个,在多个方法中调用countDown()方法,可以用来确保只有多个方法的countDown()方法都执行后。他们才会才会执行接下来的代码。
不过在spring的这个demo中初始计数器为1,我们尝试注释到Runner中await方法发现发送和消费信息也可以正常的打印,因为只要Receiver中的latch.countDown()
执行一次计数器就会减为0当前线程代码就会执行。 那么这里Runner中的await在这里有什么用呢?
我们再来看看await()这个方法,它阻塞的是当前的线程。也就是会阻塞Runner这个线程,而在我们这个demo中await()方法后并没有后续的代码逻辑,导致我们看不到await()的作用。我们在await()方法后边打印一行日志logger.info("finished")
然后分别注释掉await()和不注释执行看下结果:
//注释掉await()方法
Sending message...
finished
Received <Hello from RabbitMQ!>
//没有注释掉await()方法
Sending message...
Received <Hello from RabbitMQ!>
finished
这下大家就很容易理解CountDownLatch和await()的作用了