以下是代码演示
ExtLock
package com.burgess.net.lock;
/**
* 使用基于zk实现分布式锁
* @ClassName: ExtLock
* @Description: TODO
* @author BurgessLee
* @date 2019年6月27日
*
*/
public interface ExtLock {
//获取锁
public void getLock();
//释放锁
public void unLock();
}
定义的锁接口。
ZookeeperAbstractLock
锁接口实现的抽象类代码
package com.burgess.net.lock;
import java.util.concurrent.CountDownLatch;
import org.I0Itec.zkclient.ZkClient;
/**
* 模板设计模式
* @ClassName: ZookeeperAbstractLock
* @Description: TODO
* @author BurgessLee
* @date 2019年6月27日
*
*/
public abstract class ZookeeperAbstractLock implements ExtLock{
private static final String CONNECT = "127.0.0.1:2181";
protected ZkClient zkClient = new ZkClient(CONNECT);
protected CountDownLatch countDownLatch = null;
protected String lockPath = "/lock";
//获取锁
public void getLock() {
//1.连接zk,在zk上创建节点,类型为临时
//2.如果节点获取成功,直接执行业务逻辑,如果节点创建失败,进行等待
if(tryLock()) {
System.out.println("获取锁成功");
}else {
//3.使用事件通知监听该节点是否被删除,如果删除重新进入获取锁资源
waitLock();
getLock();
}
}
//如果获取失败,进入事件监听
protected abstract void waitLock();
//获取锁支援,如果能够获取成功
protected abstract boolean tryLock();
//释放锁
public void unLock() {
//当程序执行完毕,关闭连接
if(zkClient != null) {
zkClient.close();
System.out.println("释放锁成功,。。。。。。。。。。。");
}
}
}
ZookeeperDistributeLock
获取锁和等待获取锁实现代码
package com.burgess.net.lock;
import java.util.concurrent.CountDownLatch;
import org.I0Itec.zkclient.IZkDataListener;
/**
* 基于zk实现分布式锁
* @ClassName: ZookeeperDistributeLock
* @Description: TODO
* @author BurgessLee
* @date 2019年6月27日
*
*/
public class ZookeeperDistributeLock extends ZookeeperAbstractLock{
//获取锁
@Override
protected boolean tryLock() {
try {
zkClient.createEphemeral(lockPath);
return true;
} catch (Exception e) {
//如果创建该节点失败,直接走catch
return false;
}
}
//事件监听进行等待
@Override
protected void waitLock() {
IZkDataListener iZkDataListener = new IZkDataListener() {
//节点被删除
public void handleDataDeleted(String dataPath) throws Exception {
if(countDownLatch != null) {
//计数器为0,那么可以执行后面的代码
countDownLatch.countDown();
}
}
//节点发生改变
public void handleDataChange(String dataPath, Object data) throws Exception {
}
};
//监听事件通知
zkClient.subscribeDataChanges(lockPath, iZkDataListener);
if(zkClient.exists(lockPath)) {
countDownLatch = new CountDownLatch(1);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//为了不影响程序的效率,删除该事件监听
zkClient.unsubscribeDataChanges(lockPath, iZkDataListener);
}
}
测试例程如下:
生成订单号代码
package com.burgess.net.single;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 生成订单号
* @ClassName: OrderNumberGenerator
* @Description: TODO
* @author BurgessLee
* @date 2019年6月27日
*
*/
public class OrderNumberGenerator {
//使用时间戳实现
private int count = 0;
/**
* 生成订单号
* 单台服务器,多个线程同时访问,线程安全
* @Title: getNumber
* @Description: TODO
* @param @return
* @return String
* @throws
*/
public String getNumber() {
try {
Thread.sleep(2000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
return sdf.format(new Date())+"-"+ ++count;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
测试分布式锁代码
package com.burgess.net.lock;
import com.burgess.net.single.OrderNumberGenerator;
/**
* 测试zk分布式锁
* 如果执行的时候,强制关闭的时候会有延迟,那么可能导致死锁
* @ClassName: TestZkDistributeLock
* @Description: TODO
* @author BurgessLee
* @date 2019年6月27日
*
*/
public class TestZkDistributeLock implements Runnable{
private OrderNumberGenerator orderNumberGenerator = new OrderNumberGenerator();
private ExtLock lock = new ZookeeperDistributeLock();
//线程上锁
public void getNumber() {
try {
lock.getLock();
String number = this.orderNumberGenerator.getNumber();
System.out.println(Thread.currentThread().getName() + ",number="+ number);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unLock();
}
}
public void run() {
getNumber();
}
//服务器单机版本,生成订单号,可以使用synchronized或者lock实现效果
public static void main(String[] args) {
for(int i = 0 ; i < 100; i++) {
new Thread(new TestZkDistributeLock()).start();
}
}
}
以上就是所有实现的所有代码,如果问题,请留言,欢迎关注。