Zookeeper应用之——栅栏(barrier)

栅栏(barrier)简介

barrier的作用是所有的线程等待,知道某一时刻,锁释放,所有的线程同时执行。举一个生动的例子,比如跑步比赛,所有 运动员都要在起跑线上等待,直到枪声响后,所有运动员同时起跑,冲向终点。在这个例子中,所有的运动员就是所有的线程, 枪声是所有线程的共享锁,枪声一响,锁释放,所有线程同时执行。

java的concurrent包中已经为我们提供了barrier的实现,它叫做CyclicBarrier。但是它只能在一个java进程中提供barrier, 在分布式、集群的情况下,java是不能提供barrier的。在分布式、集群的环境下,我们需要借助外部工具实现barrier,今天我们 介绍使用zookeeper实现barrier。

Zookeeper实现Barrier的方式

Zookeeper的安装,无论是集群还是单点,请参阅其他文档,这里不再赘述了。Zookeeper的基本概念,如:节点、临时节点、 树结构、观察器(watcher)等请参阅上一篇文章,这里也不细讲。

我们通过在Zookeeper设置栅栏节点实现Barrier,节点的名字我们叫做/zookeeper/barrier,具体的逻辑如下:

  1. 客户端在Barrier节点上调用exists()方法,并设置观察器
  2. 如果Barrier节点不存在,则线程继续执行
  3. 如果Barrier节点存在,则线程等待,直到触发观察器事件,并且事件是Barrier节点消失的事件,唤起线程

具体程序实现

首先连接Zookeeper,创建Barrier节点,如下:

Zookeeper应用之——栅栏(barrier)

然后我们创建类BarrierExample,如下:

Zookeeper应用之——栅栏(barrier)

Zookeeper应用之——栅栏(barrier)

Zookeeper应用之——栅栏(barrier)

BarrierExample实现了Runnable和Watcher接口,线程开始时,会调用run()方法,发现Barrier节点存在,线程等待。 然后我们将Barrier节点删除,触发Watch事件,发现Barrier节点已消失,唤起等待的线程。接下来,创建主函数类:

Zookeeper应用之——栅栏(barrier)

我们创建了5个线程,发现Barrier节点,等待,具体执行如下:

运行main()函数,后台打印结果如下:

Zookeeper应用之——栅栏(barrier)

然后我们将Barrier节点删除:

Zookeeper应用之——栅栏(barrier)

Barrier节点消失,唤起所有等待线程,后台打印结果如下:

Zookeeper应用之——栅栏(barrier)

Zookeeper的Barrier实现就介绍完了。以后我们还会介绍Zookeeper的其他应用。


分享到:


相關文章: