package zk.lock;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class ZkDistributedClient {
// overtime time
private static final int SESSION_TIMEOUT = 5000;
// list of zookeeper servers
private String hosts = "127.0.0.1:2181";
private String groupNode = "locks1";
//private String subNode = "sub";
private ZooKeeper zk;
// The child node created by the current client
private String thisPath;
// The child node that the current client is waiting for
private String waitPath;
private CountDownLatch latch = new CountDownLatch(1);
//return result
public String result =null;
/**
* Connect to zookeeper
* subNode temporary node header
* data data
*/
public String connectZookeeper(String subNode,String data) throws Exception {
final String fdata = date;
zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() {
public void process(WatchedEvent event) {
try {
// When the connection is established, open the latch and wake up the thread waiting on the latch
if (event.getState() == KeeperState.SyncConnected) {
latch.countDown();
}
// The delete event of waitPath occurred
if (event.getType() == EventType.NodeDeleted && event.getPath().equals(waitPath)) {
// Check if thisPath is really the smallest node in the list
List<String> childrenNodes = zk.getChildren("/" + groupNode, false);
String thisNode = thisPath.substring(("/" + groupNode + "/").length());
// sort
Collections.sort(childrenNodes);
int index = childrenNodes.indexOf(thisNode);
if (index == 0) {
// is indeed the smallest node
String t = doSomething(fdata);
System.out.println("watch:::"+t);
result = t;
} else {
// Explain that waitPath is hung up due to an exception
// update waitPath
waitPath = "/" + groupNode + "/" + childrenNodes.get(index - 1);
// Re-register the listener, and determine whether the waitPath has been deleted at this time
if (zk.exists(waitPath, true) == null) {
String tt = doSomething (trusted);
System.out.println("watch===watch:::"+tt);
result = tt;
}
}
}
} catch (Exception e) {
e.printStackTrace ();
}
}
});
// wait for the connection to be established
latch.await();
// create child nodes
thisPath = zk.create("/" + groupNode + "/" + subNode, null, Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
// wait for a while to make the result clearer
Thread.sleep(10);
// Note that it is not necessary to monitor the changes of the child nodes of "/locks"
List<String> childrenNodes = zk.getChildren("/" + groupNode, false);
// There is only one child node in the list, that must be thisPath, indicating that the client has obtained the lock
if (childrenNodes.size() == 1) {
return doSomething(data);
} else {
String thisNode = thisPath.substring(("/" + groupNode + "/").length());
System.out.println(thisNode +"--------------");
// sort
Collections.sort(childrenNodes);
int index = childrenNodes.indexOf(thisNode);
if (index == -1) {
// never happened
} else if (index == 0) {
// inddx == 0, indicating that thisNode is the smallest in the list, and the current client obtains the lock
return doSomething(data);
} else {
// Get the node that ranks 1st before thisPath
this.waitPath = "/" + groupNode + "/" + childrenNodes.get(index - 1);
// Register the listener on waitPath, when waitPath is deleted, zookeeper will call back the listener's process method
zk.getData(waitPath, true, new Stat());
return null;
}
}
return null;
}
private String doSomething(String data) throws Exception {
try {
System.out.println("gain lock: " + thisPath+"----"+data);
byte[] by= zk.getData("/locknum", null, null);
String num = new String(by);
System.out.println(num+" :::::current value----------------------------");
Integer newNum = Integer.parseInt(num) -1;
zk.setData("/locknum", newNum.toString().getBytes(), -1);
System.out.println(newNum+":::::final value----------------------------");
Thread.sleep(2000);
// do something
} finally {
System.out.println("finished: " + thisPath);
// Delete thisPath, the client listening to thisPath will be notified
// Equivalent to releasing the lock
zk.delete(this.thisPath, -1);
}
return data;
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < 5; i++) {
new Thread() {
public void run() {
try {
ZkDistributedClient dl = new ZkDistributedClient();
String s = dl.connectZookeeper("gao","test");
System.out.println("return-=========="+s);
System.out.println("return========================"+dl.result);
} catch (Exception e) {
e.printStackTrace ();
}
}
}.start();
}
Thread.sleep(Long.MAX_VALUE);
}
}