【并发编程】- CyclicBarrier 屏障重置

166 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

方法getNumberWaiting()和getParties()的使用

实现代码如下:

public class CyclicBarrierPartiesService {
    public CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
        @Override
        public void run() {
            System.out.println(" 彻底结束了 " + System.currentTimeMillis());
        }
    });

    public void startMethod() {
        try {
            System.out.println(Thread.currentThread().getName() + " 准备!" + System.currentTimeMillis());
            if (Thread.currentThread().getName().equals("Thread-1")) {
                Thread.sleep(Integer.MAX_VALUE);
            }
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()+" 开始! "+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

线程执行代码如下:

public class FirstThread implements Runnable{
    private CyclicBarrierPartiesService service;

    public FirstThread(CyclicBarrierPartiesService service){
        super();
        this.service=service;
    }

    @Override
    public void run() {
        service.startMethod();
    }
}
public class SecondThread implements Runnable {
    private CyclicBarrierPartiesService service;

    public SecondThread(CyclicBarrierPartiesService service){
        super();
        this.service=service;
    }

    @Override
    public void run() {
        service.startMethod();
    }
}

运行类代码如下:

public class CyclicBarrierPartiesRun {
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrierPartiesService service = new CyclicBarrierPartiesService();
        FirstThread firstThread = new FirstThread(service);
        new Thread(firstThread).start();
        SecondThread secondThread = new SecondThread(service);
        new Thread(secondThread).start();

        Thread.sleep(5000);
        System.out.println("屏障对象的parties个数为"+service.cyclicBarrier.getParties());
        System.out.println("在屏障处等待的线程个数为"+service.cyclicBarrier.getNumberWaiting());
    }
}

运行结果如下:

Thread-0 准备!1650613215795
Thread-1 准备!1650613215801
屏障对象的parties个数为2
在屏障处等待的线程个数为1

从运行结果可看出getNumberWaiting()的作用是有几个线程已经到达屏障点,方法getParties()的作用是取得parties个数。

方法reset()的使用

实现代码如下:

public class CyclicBarrierResetService {
    public CyclicBarrier cyclicBarrier=new CyclicBarrier(3, new Runnable() {
        @Override
        public void run() {
            System.out.println(" 彻底结束了 "+System.currentTimeMillis());
        }
    });

    public void startMethod(){
        try {
            System.out.println(Thread.currentThread().getName()+" 准备! "+System.currentTimeMillis());
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName()+" 结束! "+System.currentTimeMillis());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

两个线程执行代码如下:

public class FirstThread implements Runnable{
    private CyclicBarrierResetService service;

    public FirstThread(CyclicBarrierResetService service){
        super();
        this.service=service;
    }

    @Override
    public void run() {
        service.startMethod();
    }
}
public class SecondThread implements Runnable {
    private CyclicBarrierResetService service;

    public SecondThread(CyclicBarrierResetService service){
        super();
        this.service=service;
    }

    @Override
    public void run() {
        service.startMethod();
    }
}

运行类代码如下:

public class CyclicBarrierResetRun {
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrierResetService service = new CyclicBarrierResetService();
        FirstThread firstThread = new FirstThread(service);
        new Thread(firstThread).start();
        Thread.sleep(5000);
        service.cyclicBarrier.reset();
    }
}

运行结果如下:

Thread-0 准备! 1650527560742
Thread-1 准备! 1650527560748
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.ozx.concurrentprogram.cyclicBarrier.service.CyclicBarrierResetService.startMethod(CyclicBarrierResetService.java:22)
	at com.ozx.concurrentprogram.cyclicBarrier.entity.SecondThread.run(SecondThread.java:21)
	at java.lang.Thread.run(Thread.java:748)
java.util.concurrent.BrokenBarrierException
	at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
	at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362)
	at com.ozx.concurrentprogram.cyclicBarrier.service.CyclicBarrierResetService.startMethod(CyclicBarrierResetService.java:22)
	at com.ozx.concurrentprogram.cyclicBarrier.entity.FirstThread.run(FirstThread.java:21)
	at java.lang.Thread.run(Thread.java:748)

丛运行结果来可看屏障被重置后,2个线程出现Broken异常。所以方法reset()的作用是重置屏障。

​ 使用CountDownLatch类可以实现两种角色的线程等待对方的效果,而CyclicBarrier类可以使同类线程等待达到同步的效果,使用这两个类可以更加完善地实现线程对象之间的同步性。