一、CyclicBarrier
通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。
CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
cyclicBarrier.await();
} catch (InterruptedException|BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("停顿----------2000");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
cyclicBarrier.await();
} catch (InterruptedException|BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("停顿----------3000");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(4000);
cyclicBarrier.await();
} catch (InterruptedException|BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("停顿----------4000");
}
}).start();
上述示例实现4000毫秒后三个线程通知执行打印内容
二、 CountDownLatch类利用它可以实现类似计数器的功能
public static void main(String[] args) {
CountDownLatch countDownLatch=new CountDownLatch(2);
System.out.println(Thread.currentThread().getName()+"-----结束时间:"+SDF.format(new Date()));
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName()+"-----开始时间:"+SDF.format(new Date()));
TimeUnit.SECONDS.sleep(2);
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-----结束时间:"+SDF.format(new Date()));
},"theadA").start();
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName()+"-----开始时间:"+SDF.format(new Date()));
TimeUnit.SECONDS.sleep(3);
countDownLatch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-----结束时间:"+SDF.format(new Date()));
},"theadB").start();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-----结束时间:"+SDF.format(new Date()));
}
}
三、Semaphore(信号量)用来控制并发访问的线程数量,它通过协调各个线程来保证资源的合理使用。其内部使用的是AQS机制(concurrent包下很多类实现原理都是基于AQS)。
public static void main(String[] arr){
//模拟抢票 3个出票机,10个人抢
Semaphore semaphore=new Semaphore(3,true);
for(int i=0;i<10;i++){
new Thread(()->{
try {
//允许访问
semaphore.acquire();
System.out.println(Thread.currentThread().getName()+"-----开始时间:"+SDF.format(new Date()));
///TimeUnit.SECONDS.sleep(3);
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"-----结束时间:"+SDF.format(new Date()));
//释放锁
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"thrad"+i).start();
}
}