zookeeper实现fifo以及并发访问删除
package cn.sniper.zookeeper;
import java.io.IOException;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;
public class ZookeeperUtil {
@Test
public void helloword() {
//端口默认是2181
//String connectString = "192.168.1.231";
String connectString = "192.168.1.231:2181";
int sessionTimeout = 20000;
try {
ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent event) {
System.out.println(event);
}
});
System.out.println(zk);
zk.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void create() {
String connectString = "192.168.1.231:2181";
int sessionTimeout = 20000;
try {
ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent event) {
System.err.println("事件类型:" + event.getType());
}
});
//创建节点
zk.create("/sniper1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
}
@Test
public void fifoIn() {
String connectString = "192.168.1.231,192.168.1.232,192.168.1.233";
int sessionTimeout = 50000;
try {
ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent event) {
System.err.println("事件类型:" + event.getType());
}
});
//每个客户端连进来的时候,都在fifo下创建一个有序节点 模拟10个客户端连接进入
for(int i=0; i<10; i++) {
zk.create("/fifo/", String.valueOf(System.currentTimeMillis()).getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
}
zk.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
}
@Test
public void fifoOut() {
String connectString = "192.168.1.231,192.168.1.232,192.168.1.233";
int sessionTimeout = 30000;
try {
ZooKeeper zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
public void process(WatchedEvent event) {
System.err.println("事件类型:" + event.getType());
}
});
List children = zk.getChildren("/fifo", new Watcher() {
public void process(WatchedEvent event) {
System.err.println("事件类型:" + event.getType());
}
});
//由于节点的有序性,将节点用treeSet排序一下,取得第一个元素,就可以做到先进先出队列了
TreeSet set = new TreeSet(children);
String child = set.first();
System.err.println(child);
zk.delete("/fifo/"+child, -1);
zk.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (KeeperException e) {
e.printStackTrace();
}
}
/**
* 多线程创建有序节点不存在问题
* @throws Exception
*/
public static void fifoInMultiThread() throws Exception {
//int nThreads = Runtime.getRuntime().availableProcessors();
int nThreads = 20;
final ExecutorService service = Executors.newFixedThreadPool(nThreads);
final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 30000, new Watcher() {
public void process(WatchedEvent evet) {
}
});
final long begin = System.currentTimeMillis();
for(int i=0; i<1000; i++) {
final int j = i;
service.execute(new Runnable() {
public void run() {
try {
zk.create("/fifo/", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(j == 999) {
try {
zk.close();
service.shutdown();
System.err.println(System.currentTimeMillis() - begin);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
}
}
@Test
public void size() throws Exception {
final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
public void process(WatchedEvent evet) {
}
});
System.out.println(zk.getChildren("/fifo", new Watcher() {
public void process(WatchedEvent evet) {
}
}).size() + " =========================");
zk.close();
}
/**
* 多线程取出节点并且删除节点存在问题,synchronized解决方案
* @throws Exception
*/
public static void fifoOutMultiThread() throws Exception {
int nThreads = 20;
final ExecutorService service = Executors.newFixedThreadPool(nThreads);
final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
public void process(WatchedEvent evet) {
}
});
final long begin = System.currentTimeMillis();
for(int i=0; i<1000; i++) {
final int j = i;
service.execute(new Runnable() {
public void run() {
try {
synchronized (ZookeeperUtil.class) {
List children = zk.getChildren("/fifo", new Watcher() {
public void process(WatchedEvent arg0) {
}
});
if(children != null && children.size() > 0) {
TreeSet set = new TreeSet(children);
String pop = set.first();
System.err.println(pop);
zk.delete("/fifo/"+pop, -1);
}
}
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(j == 999) {
try {
zk.close();
service.shutdown();
System.err.println(System.currentTimeMillis() - begin);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
}
}
/**
* 多线程取出节点并且删除节点存在问题,读写锁方式
* @throws Exception
*/
public static void fifoOutMultiThreadLock() throws Exception {
final ReadWriteLock rwl = new ReentrantReadWriteLock();
int nThreads = 20;
final ExecutorService service = Executors.newFixedThreadPool(nThreads);
final ZooKeeper zk = new ZooKeeper("192.168.1.231,192.168.1.232,192.168.1.233", 50000, new Watcher() {
public void process(WatchedEvent evet) {
}
});
final long begin = System.currentTimeMillis();
for(int i=0; i<1000; i++) {
final int j = i;
service.execute(new Runnable() {
public void run() {
try {
rwl.readLock().lock();
//取得fifo下的所有直接下级节点
List children = zk.getChildren("/fifo", new Watcher() {
public void process(WatchedEvent event) {
}
});
//用treeset排好序
TreeSet set = new TreeSet(children);
//取出第一个,即最先进入的一个
String pop = set.first();
//判断是否存在
Stat stat = zk.exists("/fifo/"+pop, new Watcher() {
public void process(WatchedEvent event) {
}
});
if(stat != null) {
rwl.readLock().unlock();
rwl.writeLock().lock();
//用于多线程读的因素,有可能第一条线程读到节点还存在,紧接着第二条线程就把该节点删除了,所以,加了写锁之后还需要判断一次节点是否存在
stat = zk.exists("/fifo/"+pop, new Watcher() {
public void process(WatchedEvent event) {
}
});
if(stat != null) {
System.err.println(pop);
zk.delete("/fifo/"+pop, -1);
}
rwl.writeLock().unlock();
rwl.readLock().lock();
}
rwl.readLock().unlock();
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(j == 999) {
try {
zk.close();
service.shutdown();
System.err.println(System.currentTimeMillis() - begin);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
}
}
public static void main(String[] args) throws Exception {
//fifoInMultiThread();
//fifoOutMultiThread();
//fifoOutMultiThreadLock();
}
}