1、CountDownLatch的简单介绍:
CountDownLatch是一种通用的同步工具,用给定的计数初始化。CountDownLatch是一次性现象 - 计数无法重置。由于await方法的调用,方法阻塞直到当前计数达到零,每次调用countDown(),都会让计数值减一,之后释放所有等待的线程并await立即返回任何后续的调用 。
示例代码:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class TestCountDownLatch {
/**
*CountDownLatch的使用
*/
public static void main(String[] args) {
//计数值初始化为10
CountDownLatch countDownLatch=new CountDownLatch(10);
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread 0 start....");
//使其阻塞
countDownLatch.await();
System.out.println("Thread 0 end....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
//主程序睡眠1秒,使线程0能够确保执行到CountDownLatch调用await()方法,陷入等待中
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建10个线程,并调用CountDownLatch的countDown方法
for (int i = 1; i <=10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start....");
//使计数值减一,当计数值变为0时,调用await()方法的线程0可以继续执行。
countDownLatch.countDown();
}
},"thread"+i).start();
}
}
}
2、CyclicBarrier的简单介绍:
CyclicBarrier允许一组线程全部等待彼此到达公共障碍点,这些线程必须偶尔等待彼此。屏障称为循环,因为它可以在等待线程释放后重新使用。CyclicBarrier计数(parties)可以调用reset()方法重置其初始状态,如果任何一方当前正在等待屏障,他们将返回一个 BrokenBarrierException。
示例代码:
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
public class TestCyclicBarrier {
/**
*CyclicBarrier的使用
*/
public static void main(String[] args) {
//parties 在await()触发屏障之前必须调用的线程数
CyclicBarrier cyclicBarrier=new CyclicBarrier(10);
for (int i = 1; i <=10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start......");
try {
//线程在此等待,直到调用await()方法的线程数量等于
// CyclicBarrier的构造函数的参数parties的值时,才会放行。
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end......");
}
},"thread"+i).start();
}
try {
//睡眠两秒,等待线程执行完成
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、Semaphore的简单介绍
构造函数参数,permits:可用的初始许可数量,可设置为负数,fair:指定是否为公平锁(可选参数)。
acquire方法:获取许可,阻塞直到一个可用,或者线程被中断。获得许可证(如果有)并立即返回,将可用许可证数量减少一个。
release方法:发布许可证,将其返回信号量。发布许可证,将可用许可证数量增加一个。如果任何线程试图获得许可,则选择一个并给予刚刚发布的许可。该线程被(重新)启用以进行线程调度。
acquire方法和release方法都可以传入一个可选参数int permit,代表一次获得或释放的许可数量。(不传入参数的情况下,默认获得或释放一个许可)。
还有tryAcquire与tryRelease方法尝试获取或释放许可,具体可阅读Semaphore类的API。
示例代码:
import java.util.concurrent.Semaphore;
public class TestSemaphore {
/**
*Semaphore的使用
*/
public static void main(String[] args) {
//参数permits:可用的初始许可数量,fair指定是否为公平锁
Semaphore semaphore=new Semaphore(1,false);
for (int i = 0; i <11; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" start.....");
try {
//获得一个许可,获得许可方可继续执行,没有许可需要阻塞
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" end.....");
//释放一个的许可
semaphore.release();
}
}).start();
}
}
}