Semaphore
semaphore又称信号量,在并发编程中,通过许可证控制线程并发数
new Semaphore(N,isFair) ;
n是同时运行线程数,fair是否公平,默认false;
公平:在获取许可时首先查看等待队列中是否已有线程,如果有就加入队列末尾,等待唤醒。
非公平:在获取许可时,先尝试获取许可,如果失败才会加入队列。
acquire(); 获取许可,许可数减1。
release();释放许可,许可数加1。
代码示例:
public static void main(String[] args) throws Exception {
// 允许5个线程同时执行,默认非公平
Semaphore sp = new Semaphore(5);
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
try {
// 获取许可,许可数减1
sp.acquire();
System.out.println(Thread.currentThread().getName() + "===开始");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "结束");
// 释放许可,许可数加1
sp.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
CountDownLatch
CountDownLatch是一个计数器,主要功能是通过await()方法来阻塞当前线程,然后等待计数器减少到0,
再唤起当前线程继续执行。
CountDownLatch与Semaphore相似,不同的是Semaphore的值释放一个就执行其它线程,而CountDownLatch
等到计数值为0时再执行。
new CountDownLath(N); N:允许N个线程同时执行,也就是计数值
await(); 阻塞当前线程,等待计数器为0时再执行
await(Long timeout, TimeUnit unit); 阻塞当前线程,等待一段时间,如果计数器还没变成0就会继续执行
countDown(); 计数值减1
代码示例:
public static void main(String[] args) throws Exception {
CountDownLatch cdl = new CountDownLatch(5);
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "===正在执行");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "===结束");
//计数值减1
cdl.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
System.out.println("等待===");
cdl.await();
System.out.println("继续执行");
}
CyclicBarrier
CyclicBarrier通过设置关卡让一组线程等待至某个状态之后再全部同时执行。
new CyclicBarrier(N,Runnable);N:允许N个线程同时执行;Runnable:所有线程执行完的额外操作
await(); 阻塞当前线程,等待计数器为0时再执行
await(Long timeout, TimeUnit unit); 阻塞当前线程,等待一段时间,如果计数器还没变成0就会继续执行
代码示例:
public static void main(String[] args) {
// 同时允许5个线程运行, 所有线程执行完之后的额外操作
CyclicBarrier cb = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("开始=====");
}
});
for (int i = 0; i < 10; i++) {
new Thread() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "准备好了===");
//等待所有线程执行完成
cb.await();
System.out.println(Thread.currentThread().getName() + "比赛中===");
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}