7.1 减少计数 CountDownLatch
概念:
CountDownLatch 这个类使其他线程各自执行完毕后,这个线程才去执行。- 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
代码模拟:6个同学都走了之后,班长锁门
假设我们用普通方法模拟:
package juc;
public class CountDownLatchDemo {
public static void main(String[] args) {
for(int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + ":离开了教室");
}, String.valueOf(i)).start();
}
System.out.println("班长锁门了走人了");
}
}
那么有的线程可能执行的比较慢,人还没走完,班长就锁门了: 使用CountDownLatch:
package juc;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(6);
for(int i = 0; i < 6; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + ":离开了教室");
countDownLatch.countDown();
}, String.valueOf(i)).start();
}
countDownLatch.await();
System.out.println("班长锁门了走人了");
}
}
7.2 循环栅栏 CyclicBarrier
一个可以循环利用的屏障。
它的作用是等所有线程都执行完某一动作后才继续往下执行。
就像在餐厅吃饭,有的朋友早到,有的朋友晚到,但是餐厅规定必须所有人到齐才能进去吃饭。这里的人相当于线程,餐厅相当于循环屏障。
代码演示:
package juc;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
private static final int NUMBER = 7;
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, ()->{
System.out.println("集齐7颗龙珠召唤神龙");
});
for(int i = 0; i < 7; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"星龙珠被收集到了");
try {
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}, String.valueOf(i)).start();
}
}
}
7.3 信号灯 Semaphore
semaphore 是synchronized 的加强版,用于控制并发线程的数量。
《操作系统》里讲的信号量机制
代码演示:
package juc;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for(int i = 0; i < 6; i++) {
new Thread(()->{
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "停好了");
Thread.sleep(new Random().nextInt(1000));
System.out.println(Thread.currentThread().getName() + "开走了");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
|