线程的join方法和countdownlatch类
线程的join方法和countdownlatch类
线程之间的状态有5种初始、就绪、运行、阻塞、死亡,大家应该都知道,线程在由运行态到阻塞态时有一种方法join。Join的功能和CountDownLatch类似,可以让所有子线程跑完再执行主线程。下面举例子说明两个的用法
1.线程的join方法,控制执行情况,实现主线程等待子线程。
我们可以拿Dota游戏来举例,在我们玩的时候可以进行单挑(Solo),玩过的应该不陌生,游戏我们认定为主线程,自己和对方定义为子线程,自己和对方的准备也就是加入A和B队伍中,加入队伍我们认定是子线程的任务。只有当己方和对方都准备好(进入各自队伍),游戏就会自动开始(对战平台自己触发的)
publicclass ThreadJoinShow {
privateclass ASubThread implements Runnable{
private String name;
public ASubThread(String name) {
this.name = name;
}
@Override
publicvoid run() {
System.out.println(name+"======正在加入游戏===");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"======准备好了===");
}
}
privateclass BSubThread implements Runnable{
private String name;
public BSubThread(String name) {
this.name = name;
}
@Override
publicvoid run() {
System.out.println(name+"======正在加入游戏===");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"======准备好了===");
}
}
@Test
publicvoid testNoJoin() throws InterruptedException {
System.out.println("魔兽初始界面加载请选择阵营====start");
ASubThread asub = new ASubThread("天灾方选手A");
BSubThread bsub = new BSubThread("近卫方选手B");
Thread at = new Thread(asub);
Thread bt = new Thread(bsub);
at.start();
bt.start();
System.out.println("魔兽争霸之Dota====进度条走完===进入游戏===end");
Thread.sleep(10000);//主线程暂停10s是为了防止主线程结束子线程也会跟着结束
}
@Test
publicvoid testJoin() throws InterruptedException {
System.out.println("Join版魔兽初始界面加载请选择阵营====start");
ASubThread asub = new ASubThread("Join版===天灾方选手A");
BSubThread bsub = new BSubThread("Join版===近卫方选手B");
Thread at = new Thread(asub);
Thread bt = new Thread(bsub);
at.start();
bt.start();
try {
at.join();
bt.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Join版魔兽争霸之Dota====进度条走完===进入游戏===end");
Thread.sleep(10000);//主线程暂停10s是为了防止主线程结束子线程也会跟着结束
}
}
执行测试方法console控台打印日志分别如下:
魔兽初始界面加载请选择阵营====start
魔兽争霸之Dota====进度条走完===进入游戏===end
天灾方选手A======正在加入游戏===
近卫方选手B======正在加入游戏===
天灾方选手A======准备好了===
近卫方选手B======准备好了===
Join版魔兽初始界面加载请选择阵营====start
Join版===天灾方选手A======正在加入游戏===
Join版===近卫方选手B======正在加入游戏===
Join版===天灾方选手A======准备好了===
Join版===近卫方选手B======准备好了===
Join版魔兽争霸之Dota====进度条走完===进入游戏===end
由日志可以发现,用了join方法后,主线程会等待子线程执行完,所以正常的游戏流程应该用join版,只有大家都准备好了,才能进入游戏。
2.CountDownLatch类也可以实现上述的功能,就是等所有子任务都跑完了,主线程再往下执行。
CountDownLatch有两个方法是我们常用的:await();和countDown();await()函数用于阻塞当前线程直到CountDownLatch的计数值变为0;countDown()方法用于将当前CountDownLatch的计数值减1。举个例子,假设有个女子组合TF girls要参加中戏的艺考,三个人有表演唱歌有表演朗诵有表演舞蹈,只有都通过了,才能拿到中戏的录取通知书,代码如下: public class ThreadCountDownLatchShow {
class SingSongTask implements Runnable{
private CountDownLatch countDownLatch;
public SingSongTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
publicvoid run() {
try {
System.out.println("===A表演唱歌的===start");
Thread.sleep(3000);
System.out.println("===A表演唱歌的==表演结束==end");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ReadPoetryTask implements Runnable{
private CountDownLatch countDownLatch;
public ReadPoetryTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
publicvoid run() {
try {
System.out.println("===B表演朗读的===start");
Thread.sleep(6000);
System.out.println("===B表演朗读的==表演结束==end");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class DanceTask implements Runnable{
private CountDownLatch countDownLatch;
public DanceTask(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
publicvoid run() {
try {
System.out.println("===C表演跳舞的===start");
Thread.sleep(5000);
System.out.println("===C表演跳舞的==表演结束==end");
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Test
publicvoid testGetZhongxiNotice() throws InterruptedException {
System.out.println("===TF girls参加中戏考试===");
CountDownLatch countDownLatch = new CountDownLatch(3);
ExecutorService proctorExec = Executors.newFixedThreadPool(3);
proctorExec.execute(new SingSongTask(countDownLatch));
proctorExec.execute(new ReadPoetryTask(countDownLatch));
proctorExec.execute(new DanceTask(countDownLatch));
countDownLatch.await();
proctorExec.shutdown();
System.out.println("===TF girls参加中戏考试===考试结束===通过===发录取通知书==");
}
}
执行测试方法console控台打印日志分别如下:
===TF girls参加中戏考试===
===A表演唱歌的===start
===B表演朗读的===start
===C表演跳舞的===start
===A表演唱歌的==表演结束==end
===C表演跳舞的==表演结束==end
===B表演朗读的==表演结束==end
===TF girls参加中戏考试===考试结束===通过===发录取通知书==
推荐阅读
-
Javascript中类式继承和原型式继承的实现方法和区别之处
-
[python] 在 python2和3中关于类继承的 super方法简要说明
-
PHP取得一个类的属性和方法的实现代码
-
详解Javascript百度地图接口开发文档中的类和方法
-
PowerShell中调用.NET对象的静态方法、静态属性和类方法、类属性例子
-
iOS多线程应用开发中使用NSOperation类的基本方法
-
Python自定义一个数组类,支持数组之间的四则运算和其他常见方法
-
Thread类中join方法的实现原理
-
荐 浅谈Java中类和对象的初始化、实例化以及方法重载的底层机制
-
Math类中round、ceil和floor方法的功能