刚开始的时候我不能很好的理解门栓与循环等待的区别。书上讲的也不够清晰,说CyclicBarrier锁的是事务。
后来想了想觉得门栓就像一个准点出发的大巴车,它才不管有多少人await它只管时间到了才出发也就是count降到0。
而循环等待这个大巴车是看人数只要await的人数到了一定的界限就会发车。
使用的时候门栓的countdown+await=循环等待的await。这样看来门栓要比await更为灵活。
门栓示例
public class Test {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 5; i++)
new Thread(() -> {
try {
latch.await();
System.out.println("观察阻塞情况");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
for (int i = 0; i < 5; i++)
new Thread(() -> {
synchronized (Test.class) {
latch.countDown();
System.out.println(latch.getCount());
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
运行结果
循环等待示例
public class Test {
public static void main(String[] args) {
CyclicBarrier cb = new CyclicBarrier(3);
for (int i = 0; i < 2; i++)
new Thread(() -> {
try {
System.out.println("线程" + Thread.currentThread().getName() + "被阻塞");
cb.await();
System.out.println("阻塞解除");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, "" + i).start();
//主线程中
try {
TimeUnit.SECONDS.sleep(3);
System.out.println("线程"+Thread.currentThread().getName()+"被阻塞");
cb.await();
System.out.println("阻塞解除");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
运行结果
循环等待的构造函数中还可以加一个线程该线程在等待完成后优先执行,一般用于收尾工作代码如下:
CyclicBarrier cb = new CyclicBarrier(3,()-> System.out.println("阻塞解除"));
信号量Semaphore类
public class Test {
public static void main(String[] args) {
Semaphore sema = new Semaphore(2,true);//可以设置是否公平
for(int i = 0;i<10;i++)
new Thread(()->{
try {
sema.acquire();
System.out.println(Thread.currentThread().getName()+"请求信号量");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
sema.release();
System.out.println(Thread.currentThread().getName()+"释放信号量");
}
},"线程"+i).start();
}
}
运行结果: