java多线程[7]:CyclicBarrier

cyclic的意思是周期,barrier的意思是障碍或栅栏。CyclicBarrier提供了一种很有意思的线程间保持步调一致的方案,它的工作机制是:它在初始化时设置一个周期数量,表示为n,当某个线程都调用了CyclicBarrier对象的await()方法时,当前线程会挂起,直到n个或n的整数倍个线程都调用await()方法时,这个周期完成了,将一次性唤醒所有因调用了await()方法而挂起的线程,并且还可以启动一个周期线程。

下面是CyclicBarrier类的两个构造方法

public CyclicBarrier(int parties)
public CyclicBarrier(int parties, Runnable barrierAction)

第一个方法的parties参数指定了一个周期数量,第二个重载的barrierAction参数还可以指定一个周期线程,当周期完成时将被启动。

看一个示例代码可能更容易让你明白。假设有三个worker thread,他们都做着周期性的事情,每个worker thread的工作效率不一样,有的快些有的慢些,但每完成一个任务周期,他们都需要一起讨论一下,然后再开始下一个周期的工作。由于有的快有的慢,先完成任务的线程可以调用CyclicBarrier.await()挂起,等到三个线程都调用了该方法,说明这个周期完成了。

下来看worker thread

public class MyWorker implements Runnable {

    int interval;
    String workerName;
    CyclicBarrier cyclicBarrier;

    public MyWorker(int interval, String workerName, CyclicBarrier cyclicBarrier) {
        this.interval = interval;
        this.workerName = workerName;
        this.cyclicBarrier = cyclicBarrier;
        new Thread(this).start();
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(workerName + " runs " + i);
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (i > 0 && i % 3 == 0) {
                try {
                    System.out.println(workerName + " await ---------");
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

通过传递interval参数来影响当前thread的工作时间,可以理解为interval比较大的线程的工作效率比较低。每个线程要完成10个任务,但每完成3个就要调用cyclicBarrier.await()来和其他线程同步一下进度。

下面是周期线程

public class Meeting implements Runnable {
    @Override
    public void run() {
        System.out.println("it's time to have a rest ");
    }
}

下面是main方法

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Meeting());

        new MyWorker(200, "worker1", cyclicBarrier);
        new MyWorker(500, "worker2", cyclicBarrier);
        new MyWorker(1000, "worker3", cyclicBarrier);

    }
}

在main方法中,首先创建了一个CyclicBarrier,设置了周期为3,还指定了周期线程。然后启动了三个worker thread。尽管每个thread的速度都不一样,但每完成三个任务后,这三个线程都会等一等其他线程,直到三个线程都完成了三个(或三的整数倍个)任务后,当前周期完成,启动周期线程,然后再开始下一个周期的工作。

上面代码的输出结果是:

worker1 runs 0
worker2 runs 0
worker3 runs 0
worker1 runs 1
worker1 runs 2
worker2 runs 1
worker1 runs 3
worker1 await ---------
worker3 runs 1
worker2 runs 2
worker2 runs 3
worker3 runs 2
worker2 await ---------
worker3 runs 3
worker3 await ---------
it's time to have a rest 
worker3 runs 4
worker1 runs 4
worker2 runs 4
worker1 runs 5
worker1 runs 6
worker2 runs 5
worker1 await ---------
worker3 runs 5
worker2 runs 6
worker2 await ---------
worker3 runs 6
worker3 await ---------
it's time to have a rest 
worker3 runs 7
worker1 runs 7
worker2 runs 7
worker1 runs 8
worker1 runs 9
worker2 runs 8
worker1 await ---------
worker3 runs 8
worker2 runs 9
worker2 await ---------
worker3 runs 9
worker3 await ---------
it's time to have a rest

你可能感兴趣的:(java,se,java进阶教程)