这三个类都属于java.util.concurrent包下的,用于保证线程安全,用比较简明的话讲,这三个类的主要功能为:
- Countdownlatch:指定数量的线程执行完后才能向下执行。
- CyclicBarrier:指定数量的线程到达屏障之后,一起向下执行
- Semaphore:只允许指定数量的线程同时执行
具体参照下面的详细介绍
CountDownLatch
CountDownLatch可以实现类似计数器的功能。如果一个线程向下继续执行的条件是需要一定数量的任务完成,每个任务完成时都会通知CountDownLatch对象,如果有任务未完成,当前线程处于阻塞状态,直到指定数量的任务都完成了,才向下继续运行。
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
System.out.println("等待子线程执行完毕...");
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子线程," +
Thread.currentThread().getName() + "开始执行...");
countDownLatch.countDown();// 每次减去1
System.out.println("子线程," +
Thread.currentThread().getName() + "结束执行...");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子线程," +
Thread.currentThread().getName() + "开始执行...");
countDownLatch.countDown();
System.out.println("子线程," +
Thread.currentThread().getName() + "结束执行...");
}
}).start();
countDownLatch.await();// 调用当前方法主线程阻塞 countDown结果为0, 阻塞变为运行状态
System.out.println("两个子线程执行完毕....");
System.out.println("继续主线程执行..");
}
}
CyclicBarrier
循环屏障(CyclicBarrier)初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。
class Writer extends Thread {
private CyclicBarrier cyclicBarrier;
public Writer(CyclicBarrier cyclicBarrier){
this.cyclicBarrier=cyclicBarrier;
}
@Override
public void run() {
System.out.println("线程" +
Thread.currentThread().getName() + ",正在写入数据");
try {
Thread.sleep(3000);
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("线程" +
Thread.currentThread().getName() + ",写入数据成功.....");
try {
cyclicBarrier.await();
} catch (Exception e) {
}
System.out.println("所有线程执行完毕..........");
}
}
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier=new CyclicBarrier(5);
for (int i = 0; i < 5; i++) {
Writer writer = new Writer(cyclicBarrier);
writer.start();
}
}
}
Semaphore
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:
- availablePermits函数用来获取当前可用的资源数量
- wc.acquire(); //申请资源
- wc.release();// 释放资源
class TestSemaphore extends Thread{
private Semaphore sp ;
public TestSemaphore(Semaphore sp) {
this.sp = sp;
}
@Override
public void run() {
String t_name = getName();
try {
//System.out.println(t_name + "可用:" + availablePermits);
sp.acquire();
System.out.println(t_name + "获取信号锁...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
sp.release();
System.out.println(t_name + "释放信号锁...");
}
}
}
public class ThreadDemo3 {
public static void main(String[] args) {
Semaphore sp = new Semaphore(3);
for (int i = 0; i < 10; i++) {
TestSemaphore ts = new TestSemaphore(sp);
ts.setName(i + 1 + "");
ts.start();
}
}
}