com.alogic.zk.ZKLock Maven / Gradle / Ivy
package com.alogic.zk;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.anysoft.util.BaseException;
import com.anysoft.util.Properties;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.UPath;
/**
* 基于zk实现的全局锁
*
* @author yyduan
*
*/
public class ZKLock implements Lock, Watcher {
/**
* a logger of log4j
*/
private static Logger LOG = LoggerFactory.getLogger(ZKLock.class);
/**
* a connector to zoo keeper
*/
protected ZooKeeperConnector conn = null;
/**
* 锁在ZooKeeper下的路径
*/
protected UPath lockPath = null;
/**
* Latch
*/
protected CountDownLatch latch = null;
/**
* 在ZooKeeper中临时节点名称
*/
protected String myNode = null;
/**
* 要等待的节点
*/
protected String waitNode = null;
protected int sessionTimeout = 30000;
public ZKLock(String _lockname,Properties props){
String lockName = _lockname;
String rootPath = PropertiesConstants.getString(props, "root", "${zookeeper.lock.root}");
if (rootPath.length() <= 0){
rootPath = "/alogic/global/lock";
}
conn = new ZooKeeperConnector(props);
sessionTimeout = PropertiesConstants.getInt(props, "${zookeeper.lock.timeout}", sessionTimeout);
lockPath = new UPath(rootPath + "/" + lockName);
conn.makePath(lockPath,ZooKeeperConnector.DEFAULT_ACL, CreateMode.PERSISTENT);
markOnZooKeeper();
}
public void process(WatchedEvent event) {
if (event.getType().equals(EventType.NodeDeleted) && event.getPath().equals(lockPath + "/" + waitNode)){
if (latch != null){
latch.countDown();
}
}
}
public void lock() {
try {
lockInterruptibly();
} catch (InterruptedException e) {
LOG.info("Lock waiting thread has been interrupted,exit",e);
}
}
public void lockInterruptibly() throws InterruptedException {
LOG.info("Using " + getClass().getName() + " to lock.");
while (!tryLock(sessionTimeout,TimeUnit.MILLISECONDS)){
try {
LOG.info("Can not get the lock . Waiting ....");
Thread.sleep(1000);
} catch (InterruptedException e) {
throw e;
}
}
LOG.info("Got the lock..");
}
public Condition newCondition() {
return null;
}
protected void markOnZooKeeper(){
UPath path = lockPath.append("lock");
myNode = conn.create(path, "", ZooKeeperConnector.DEFAULT_ACL, CreateMode.EPHEMERAL_SEQUENTIAL, false);
myNode = myNode.substring(myNode.lastIndexOf("/") + 1);
}
public boolean tryLock() {
List allNodes = conn.getChildren(lockPath, this, false);
Collections.sort(allNodes);
if (myNode.equals(allNodes.get(0))){
//我就是最小的节点,取得锁
return true;
}
//找到比我小的节点
waitNode = allNodes.get(Collections.binarySearch(allNodes, myNode) - 1);
return false;
}
public boolean tryLock(long timeout, TimeUnit timeUnit){
if (tryLock()){
return true;
}
try {
return waitForLock(waitNode,timeout,timeUnit);
} catch (InterruptedException e) {
throw new BaseException("core.e1006",e.getMessage(),e);
}
}
/**
* 等待指定节点释放资源
* @param wn 等待节点
* @param timeout 超时时间
* @param timeUnit 时间但闻
* @return true|false 如果指定节点释放了资源,返回为true,否则为false
* @throws InterruptedException
*/
private boolean waitForLock(String wn, long timeout,
TimeUnit timeUnit) throws InterruptedException {
boolean exist = conn.existPath(lockPath.append(wn), this, false);
if (exist){
latch = new CountDownLatch(1);
latch.await(timeout, timeUnit);
latch = null;
return !conn.existPath(lockPath.append(wn), this, false);
}else{
return true;
}
}
public void unlock() {
conn.delete(lockPath.append(myNode), true);
conn.disconnect();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy