Synchronizer
控制多个线程的流程,比如线程执行到某一个点的时候是等待还是通过。 JDK中自带了信号量,关卡,闭锁
闭锁CoutDownLatch
达到最终状态前是关闭的,所有线程在此阻塞, 达到最终状态后开放,并且不可以再修改,所有线程进入可运行状态。
很适合,等待初始化, 等待依赖等等场景。
如:
/**
* 设置countDownLatch的初始值,
* 用await()来等待
* 用countDown来倒计时 --初始值
* 当初始值为0时await()等待被notify
*/
public class TestLatch {
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(1);
final String[] datas = new String[3];
new Thread(){
@Override
public void run() {
try {
System.out.println("等待初始化");
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("初始化完成。开始执行");
for (String data : datas) {
System.out.println(data);
}
}
}.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
datas[0] = "我";
datas[1] = "爱";
datas[2] = "你";
System.out.println("初始化完成");
latch.countDown();
}
}
信号量
适用于连接池等场景
/**
* 创建一个含有固定许可数的信号量
* 线程用acquire()标记获得了一个许可,切许可-1,当许可为0时等待,
* 用release来释放许可,许可+1,其他等待的线程可以获得许可了。
*/
public class TestSemaphore {
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 20; i++) {
new Thread("thread" + i){
@Override
public void run() {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "正在执行");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();;
}
}.start();
}
}
}
关卡
与闭锁不同的是,闭锁等待状态,而关卡是等待线程。
特别适用于把一个计算拆分成多个进行计算,最后再进行整合。
/**
* 关卡
* 定义所有线程都到关卡之后的行为及关卡中包含的线程数量
*
* 各个线程使用await方法来表示已经到这个关卡等着了
*
* 当指定数目的线程等着了,那么就开放关卡, 所有线程及刚才定义的行为都继续执行
*/
public class TestBarrier {
public static void main(String[] args) {
final String[] friends = new String[]{"1", "2", "3"};
final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("出发");
}
});
for (final String friend : friends) {
new Thread(){
@Override
public void run() {
System.out.println(friend + "到集合点了");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(friend + "出发");
}
}.start();
}
}
}
打印如下:
1到集合点了
3到集合点了
2到集合点了
出发
2出发
3出发
1出发