前言
利用countdownLatch实现多线程同步的效果,优势在于可以和线程池结合使用,相比于join逻辑更加简单。
一、使用环境
普通的maven java环境
二、过程
1.引入库
代码如下(示例):
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
2.初始参数
- 固定线程池(FixedThreadPool):参数10,模拟10个玩家。
- 结果数组(result):用于保存线程加载的字符串。
- 随机数(random):用于Thread.sleep 模拟加载延迟
- 同步器(count):使用其中的 countdown()和 awit()方法。
//创建固定大小线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//保存的数组
String[] result = new String[10];
//随机数
Random random = new Random();
//countdownLatch 保证和线程数一致
CountDownLatch count = new CountDownLatch(10);
3.模拟过程
单个线程的任务:
- 随机睡眠时间,模拟网络延迟;
- 从0~100将每个数字后方+“%”,并将结果存入result数组中
- 将result数组中的内容进行打印 注意: 使用 print + “\r”
- 使用count.countDown() 将state计数结果-1。注意: 位置一定要在一次任务执行后。
//j 表示开启线程的个数
for (int j = 0; j < 10; j++) {
//线程内不能使用变量,故使用num进行常量化
int num = j;
pool.submit(()->{
//具体任务
for (int i = 0; i <=100; i++) {
try {
//随机睡眠时间
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
result[num] = i + "%";
//打印单行结果的小技巧 : print + "\r"
System.out.print("\r"+Arrays.toString(result));
}
count.countDown();
});
}
4.结束和关闭资源
当全部线程加载结束后,state属性会变为0,此时count.await()唤醒主线程打印游戏开始,并使用pool.shutdown() 关闭线程池资源。
\n表示在下一行打印
//count.await(); 等待全部线程加载结束
count.await();
System.out.println("\n游戏开始");
//线程池关闭
pool.shutdown();
三、完整代码
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestCountDownLatch {
public static void main(String[] args) throws InterruptedException {
//创建固定大小线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//保存的数组
String[] result = new String[10];
//随机数
Random random = new Random();
//countdownLatch 保证和线程数一致
CountDownLatch count = new CountDownLatch(10);
//线程池开启
//j 表示开启线程的个数
for (int j = 0; j < 10; j++) {
//线程内不能使用变量,故使用num进行常量化
int num = j;
pool.submit(()->{
//具体任务
for (int i = 0; i <=100; i++) {
try {
//随机睡眠时间
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
result[num] = i + "%";
//打印单行结果的小技巧 : print + "\r"
System.out.print("\r"+Arrays.toString(result));
}
count.countDown();
});
}
//count.await(); 等待全部线程加载结束
count.await();
System.out.println("\n游戏开始");
//线程池关闭
pool.shutdown();
}
}