1.线程之间通信之CountDownLatch的使用
主线程等待两个子线程执行完任务再继续向下执行。
public static final Random r = new Random();
public static final CountDownLatch lock = new CountDownLatch(2);
public static void main(String[] args) {
new Thread(()->{
task("task01");
}).start();
new Thread(()->{
task("task02");
}).start();
try {
//等待CountDownLatch计数减为0
lock.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task01 与 task02 执行结束");
}
public static void task(String name){
try {
System.out.println("开始执行任务:"+name);
TimeUnit.SECONDS.sleep(r.nextInt(3));
System.out.println("结束执行任务:"+name);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//任务执行完后,CountDownLatch计数减1
lock.countDown();
}
}
2.线程之间通信之CyclicBarrier的使用
高级版CountDownLatch,可在循环中使用,调用reset方法重置计数。
public static final Random r = new Random();
public static final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
public static void main(String[] args) throws Exception{
//可复用的CountDownLatch,调用reset()方法,重置计数
for (int i = 0; i < 5; i++) {
new Thread(()->{
try {
task("task01");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
new Thread(()->{
try {
task("task02");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
//计数减1,等待减为0后继续向下执行
cyclicBarrier.await();
System.out.println("task01 与 task02 执行结束");
//重置计数
cyclicBarrier.reset();
}
}
public static void task(String name) throws Exception{
try {
System.out.println("开始执行任务:"+name);
TimeUnit.SECONDS.sleep(r.nextInt(3));
System.out.println("结束执行任务:"+name);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
//计数减1
cyclicBarrier.await();
}
}
3.线程之间通信之Semaphore的使用
信号量,可以用作流控,控制请求的并发个数
public static final Random r = new Random();
public static final Semaphore lock = new Semaphore(2);
public static void main(String[] args) throws Exception{
List<Thread> list =new ArrayList<>();
for (int i = 0; i < 10; i++) {
int finalI = i;
list.add(new Thread(()->{
try {
task("task"+ finalI);
} catch (Exception e) {
e.printStackTrace();
}
}));
}
list.forEach(t->t.start());
}
public static void task(String name) throws Exception{
try {
while (true){
//获取执行权
if(lock.tryAcquire()){
System.out.println("抢到凭证,开始执行任务:"+name);
TimeUnit.SECONDS.sleep(r.nextInt(3));
System.out.println("抢到凭证,结束执行任务:"+name);
lock.release();
break;
}
}
} catch (InterruptedException e) {
//释放执行权,供其他线程使用
lock.release();
e.printStackTrace();
}
}