代码
import java.util.concurrent.CountDownLatch;
public class testLatch {
public static void main(String[] args) {
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(2);
// try{
// System.out.println("the race begin");
// begin.countDown();
// end.await();//await() 方法具有阻塞作用,也就是说主线程在这里暂停
// System.out.println("the race end");
// }catch(Exception e){
// e.printStackTrace();
// }
for(int i=0; i<2; i++){
Thread thread = new Thread(new Player(begin,end),String.valueOf(i));
thread.start();
}
try{
System.out.println("the race begin");
begin.countDown();
end.await();//await() 方法具有阻塞作用,也就是说主线程在这里暂停 等待end倒计数器数量为0时,(主线程)继续向下执行。
System.out.println("the race end");
}catch(Exception e){
e.printStackTrace();
}
}
}
class Player implements Runnable{
private CountDownLatch begin;
private CountDownLatch end;
Player(CountDownLatch begin,CountDownLatch end){
this.begin = begin;
this.end = end;
}
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " start !");;
begin.await();//因为此时已经为0了,所以不阻塞
System.out.println(Thread.currentThread().getName() + " arrived !");
end.countDown();//countDown() 并不是直接唤醒线程,当end.getCount()为0时线程会自动唤醒
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("孙悟空等待");
try {
countDownLatch.await(); //先阻塞该线程 等到计数器为0时在进行执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("孙悟空执行");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("猪八戒等待");
try {
Thread.sleep(1000);
System.out.println("猪八戒结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("唐三藏等待");
try {
Thread.sleep(2000);
countDownLatch.countDown();
System.out.println("唐三藏结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
count是一个线程数量,只有一个构造函数,(带参数的),只会被赋值一次,没有更多的方法来重置count
private volatile int state;
volatile 每一个线程访问的值是公共的值,不建立副本,不建立缓存。
ThreadLocal 每一块线程建立一个副本
CountDownLatch结合Callable接口小实例
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Runner implements Callable {
private CountDownLatch begin; //裁判
private CountDownLatch end; //跑步的(运动员)
public Runner(CountDownLatch begin, CountDownLatch end) {
super(); //无参
this.begin = begin;
this.end = end;
}
@Override
public Object call() throws Exception {
int score = new Random().nextInt(10);
begin.await(); //裁判等待运动员上场
//跑步比赛
// TimeUnit.MICROSECONDS.sleep(10000); //跑步需要花的时间 (线程休眠时间)
//运动员跑步完成
end.countDown();
return score;
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class RunnerImpl {
public static void main(String[] args) throws InterruptedException, ExecutionException {
int person=8;
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(person);
//创建8个线程
ExecutorService executorService = Executors.newFixedThreadPool(person);
List<Future<Integer>> list = new ArrayList<>();
for (int i= 0 ;i<person;i++) {
list.add(executorService.submit(new Runner(begin,end)));
}
//枪声响起
begin.countDown(); //主线程优于开启的线程 先运行主线程(先争取cpu)
//等待所有运动员跑完 await() 方法具有阻塞作用,也就是说主线程在这里暂停 等待end倒计数器数量为0时,(主线程)继续向下执行。
end.await();
int count= 0;
int height= 0;
for (Future<Integer> f:list) {
count+=f.get();
if(f.get()>height){
height=f.get();
}
}
System.out.println("有多少运动员从: "+person+" 总分: "+count+ " 平均分: "+count/person+" 最高分 "+ height);
}
}
运行结果
参考链接
这辈子坚持与不坚持都不可怕,怕的是独自走在坚持的道路上!!!
欢迎加入技术群聊!!