CountDownLatch倒计时锁
1.基本概念
CountDownLatch用来进行线程同步协作,等待所有线程完成倒计时。
其中构造参数用来初始化等待计数值,await() 用来等待计数归零,countDown() 用来让计数减一.
CountDownLatch与CyclicBarrier的区别是:
- CountDownLatch不可以重用,当任务Task都执行完毕后结束.当再执行其他任务时,需要重新创建.
- CyclicBarrier可以重用, 任务Task执行完毕后不会结束,再执行其他任务时会继续使用当前的对象.
1.CountDownLatch基本用法
package com.concurrent.p10;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
@Slf4j(topic = "c.Test_CountDownLatch")
public class Test_CountDownLatch {
public void sleep(long second) {
try {
Thread.sleep(second * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* CountDownLatch基本用法:
* 等待3个子线程都countDown之后,唤醒主线程
*
* 09:10:01.740 [main] DEBUG c.Test_CountDownLatch - wait...
* 09:10:01.740 [Thread-2] DEBUG c.Test_CountDownLatch - begin...
* 09:10:01.740 [Thread-0] DEBUG c.Test_CountDownLatch - begin...
* 09:10:01.740 [Thread-1] DEBUG c.Test_CountDownLatch - begin...
* 09:10:03.747 [Thread-0] DEBUG c.Test_CountDownLatch - begin end...
* 09:10:05.747 [Thread-1] DEBUG c.Test_CountDownLatch - begin end...
* 09:10:07.747 [Thread-2] DEBUG c.Test_CountDownLatch - begin end...
* 09:10:07.747 [main] DEBUG c.Test_CountDownLatch - wait end...
*/
@Test
public void test1() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3);
//线程1
new Thread(() -> {
log.debug("begin...");
sleep(2);
log.debug("begin end...");
countDownLatch.countDown();
}).start();
//线程2
new Thread(() -> {
log.debug("begin...");
sleep(4);
log.debug("begin end...");
countDownLatch.countDown();
}).start();
//线程3
new Thread(() -> {
log.debug("begin...");
sleep(6);
log.debug("begin end...");
countDownLatch.countDown();
}).start();
//主线程
log.debug("wait...");
countDownLatch.await();
log.debug("wait end...");
}
}
2.CountDownLatch一般配合线程池使用
package com.concurrent.p10;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j(topic = "c.Test_CountDownLatch")
public class Test_CountDownLatch {
public void sleep(long second) {
try {
Thread.sleep(second * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* CountDownLatch配合线程池使用:
*
* 09:18:43.493 [pool-1-thread-2] DEBUG c.Test_CountDownLatch - begin...
* 09:18:43.493 [pool-1-thread-3] DEBUG c.Test_CountDownLatch - begin...
* 09:18:43.493 [pool-1-thread-1] DEBUG c.Test_CountDownLatch - begin...
* 09:18:45.498 [pool-1-thread-1] DEBUG c.Test_CountDownLatch - begin end...
* 09:18:47.499 [pool-1-thread-2] DEBUG c.Test_CountDownLatch - begin end...
* 09:18:49.498 [pool-1-thread-3] DEBUG c.Test_CountDownLatch - begin end...
* 09:18:49.498 [pool-1-thread-4] DEBUG c.Test_CountDownLatch - begin...
* 09:18:50.498 [pool-1-thread-4] DEBUG c.Test_CountDownLatch - begin end...
*/
@Test
public void test2() {
//创建一个大小为5的线程池
ExecutorService service = Executors.newFixedThreadPool(5);
//创建倒计时锁
CountDownLatch latch = new CountDownLatch(3);
//任务1
service.submit(() -> {
log.debug("begin...");
sleep(2);
log.debug("begin end...");
latch.countDown();
});
//任务2
service.submit(() -> {
log.debug("begin...");
sleep(4);
log.debug("begin end...");
latch.countDown();
});
//任务3
service.submit(() -> {
log.debug("begin...");
sleep(6);
log.debug("begin end...");
latch.countDown();
});
//任务4
service.submit(() -> {
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("begin...");
sleep(1);
log.debug("begin end...");
});
for (; ; ) ;
}
}
2.CountDownLatch应用
1.CountDownLatch应用-等待多线程准备完毕
package com.concurrent.p10;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* CountDownLatch应用-等待多线程准备完毕
*/
@Slf4j(topic = "c.Test_CountDownLatchApplication")
public class Test_CountDownLatchApplication {
public void sleep(long mills) {
try {
Thread.sleep(mills);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 所有线程都执行到100%时,主线程才能继续执行
*
* [100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%]
* 15:48:59.578 [main] DEBUG c.Test_CountDownLatchApplication - 加载完成,开始!
*/
@Test
public void test1() throws InterruptedException {
//创建大小10的线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//创建倒计时锁对象
CountDownLatch latch = new CountDownLatch(10);
//模拟随机运行时间
Random random = new Random();
//进度数组
String all[] = new String[10];
for (int j = 0; j < 10; j++) {
int k = j;
service.submit(() -> {
for (int i = 0; i <= 100; i++) {
sleep(random.nextInt(100));
all[k] = i + "%";
System.out.print("\r" + Arrays.toString(all));
}
latch.countDown();
});
}
latch.await();
log.debug("加载完成,开始!");
service.shutdown();
}
}
应用-同步等待多个远程调用结束
//TODO