cyclicbarrier
接下里用一个实例来介绍一波barrier用法:
示例1:
开学了,有多个同学来学校交作业,只有当老师喊一声交作业了,所有同学才能开始交作业,运用多线程来模拟此过程
package 多线程;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class cyclicbarrier用法 {
/*
* 该用法就是在多个线程同步执行的时候设置一个屏障点,每个线程到达那个屏障点的时候都需要等待
* 等到所有人都到达屏障点的时候才执行屏障点所指定的任务
* 最后再执行每个任务还没有执行完成的剩下的任务
* 该屏障点就是cyclicbarrier对象,每个任务执行到该对象执行的await()方法都停下来,直到达到设置的屏障点的数目,再往后执行
*/
public void meeting(CyclicBarrier barrier){
System.out.println(Thread.currentThread().getName()+"我们来学校了");
try {
Thread.sleep(1000);
barrier.await();//等待其他人一起交作业
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"交了作业");
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
final CyclicBarrier barrier=new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
// TODO 自动生成的方法存根
System.out.println("大家准备开始交作业");
}
});
final cyclicbarrier用法 m=new cyclicbarrier用法();
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO 自动生成的方法存根
m.meeting(barrier);
}
}).start();
}
}
}
————————————————
版权声明:本文为CSDN博主「不要脸的阿智」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42422465/article/details/100675377
示例2:
public class CyclicBarrierDemo {
static class TaskThread extends Thread {
CyclicBarrier barrier;
public TaskThread(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(getName() + " 到达栅栏 A");
barrier.await();
System.out.println(getName() + " 冲破栅栏 A");
Thread.sleep(2000);
System.out.println(getName() + " 到达栅栏 B");
barrier.await();
System.out.println(getName() + " 冲破栅栏 B");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int threadNum = 5;
CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 完成最后任务");
}
});
for(int i = 0; i < threadNum; i++) {
new TaskThread(barrier).start();
}
}
}
总结:一个await对应一个 完成任务呗!!
Thread-1 到达栅栏 A
Thread-3 到达栅栏 A
Thread-0 到达栅栏 A
Thread-4 到达栅栏 A
Thread-2 到达栅栏 A
Thread-2 完成最后任务
Thread-2 冲破栅栏 A
Thread-1 冲破栅栏 A
Thread-3 冲破栅栏 A
Thread-4 冲破栅栏 A
Thread-0 冲破栅栏 A
Thread-4 到达栅栏 B
Thread-0 到达栅栏 B
Thread-3 到达栅栏 B
Thread-2 到达栅栏 B
Thread-1 到达栅栏 B
Thread-1 完成最后任务
Thread-1 冲破栅栏 B
Thread-0 冲破栅栏 B
Thread-4 冲破栅栏 B
Thread-2 冲破栅栏 B
Thread-3 冲破栅栏 B
countDownLatch
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(10);
for (int i=0; i<9; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 运行");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
}
}).start();
}
System.out.println("等待子线程运行结束");
latch.await(10, TimeUnit.SECONDS);
System.out.println("子线程运行结束");
}
————————————————
版权声明:本文为CSDN博主「春风十里不及你」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq812908087/article/details/81112188
子线程等待主线程处理完毕开始处理,子线程处理完毕后,主线程输出
class MyRunnable implements Runnable {
private CountDownLatch countDownLatch;
private CountDownLatch await;
public MyRunnable(CountDownLatch countDownLatch, CountDownLatch await) {
this.countDownLatch = countDownLatch;
this.await = await;
}
@Override
public void run() {
try {
countDownLatch.await();
System.out.println("子线程" +Thread.currentThread().getName()+ "处理自己事情");
Thread.sleep(1000);
await.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
————————————————
版权声明:本文为CSDN博主「春风十里不及你」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq812908087/article/details/81112188
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
CountDownLatch await = new CountDownLatch(5);
for (int i=0; i< 5; i++) {
new Thread(new MyRunnable(countDownLatch, await)).start();
}
System.out.println("主线程处理自己事情");
Thread.sleep(3000);
countDownLatch.countDown();
System.out.println("主线程处理结束");
await.await();
System.out.println("子线程处理完毕啦");
}
————————————————
版权声明:本文为CSDN博主「春风十里不及你」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq812908087/article/details/81112188
在实时系统中的使用场景
1、实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数器为1的CountDownLatch,并让其他所有线程都在这个锁上等待,只需要调用一次countDown()方法就可以让其他所有等待的线程同时恢复执行。
2、开始执行前等待N个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统都已经启动和运行了。
3、死锁检测:一个非常方便的使用场景是你用N个线程去访问共享资源,在每个测试阶段线程数量不同,并尝试产生死锁。
MySemaphore:
package com.unicss;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class MySemaphore extends Thread {
Semaphore position;
private int id;
public MySemaphore(int i, Semaphore s) {
this.id = i;
this.position = s;
}
public void run() {
try {
if (position.availablePermits() > 0) {
System.out.println("顾客[" + this.id + "]进入厕所,有空位");
} else {
System.out.println("顾客[" + this.id + "]进入厕所,没空位,排队");
}
position.acquire();
System.out.println("顾客[" + this.id + "]获得坑位");
Thread.sleep((int) (Math.random() * 1000));
System.out.println("顾客[" + this.id + "]使用完毕");
position.release();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
ExecutorService list = Executors.newCachedThreadPool();
Semaphore position = new Semaphore(2);
for (int i = 0; i < 10; i++) {
list.submit(new MySemaphore(i + 1, position));
}
list.shutdown();
//方法acquireUninterruptibly()的作用是使等待进入acquire()方法的线程,不允许被中断。
position.acquireUninterruptibly(2);
System.out.println("使用完毕,需要清扫了");
position.release(2);
}
}