1.Zookeeper中分布式锁的实现
代码部分:
package com.atguigu.zk.case2;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class DistributeLock {
private ZooKeeper zooKeeper;
private String connectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";
private int sessionTimeout=2000;
//创建的临时节点
private String currentMode;
//前一个节点的路径
private String waitPath;
//获取连接状态,等待前一步骤执行完成后,程序才继续向下执行
//初值默认为线程数量
private CountDownLatch countDownLatch=new CountDownLatch(1);
//获取监听结果
private CountDownLatch waitLatch=new CountDownLatch(1);
public DistributeLock() throws Exception {
//获取连接
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
//如果连接上zk,释放countDownLatch
if(watchedEvent.getState()== Event.KeeperState.SyncConnected)
{
countDownLatch.countDown();
}
//waitLatch也需要释放
if(watchedEvent.getType()==Event.EventType.NodeDeleted && watchedEvent.getPath().equals(waitPath))
{
waitLatch.countDown();
}
}
});
//如果连接成功,程序会向下执行
countDownLatch.await();
//判断根节点/locks是否存在
Stat exists = zooKeeper.exists("/locks", false);
if(exists==null)
{
//创建/locks结点,永久结点
zooKeeper.create("/locks","locks".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
//加锁
public void zklock() throws Exception
{
//客户端在/locks下边创建对应的临时带序号的结点
currentMode = zooKeeper.create("/locks/" + "seq-", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
//判断创建的结点是否是序号最小的结点,如果是最小的,获取到锁,否则,监听它序号前的一个节点
List<String> children = zooKeeper.getChildren("/locks", false);
//如果只有一个节点,那么这个节点就是最小序号,获取到锁
if(children.size()==1)
{
return;
}
else {
//如果有多个结点
Collections.sort(children);
//获取结点名称seq-0000000
String nodeName = currentMode.substring("/locks/".length());
//通过结点名称获取结点的在children集合的位置
int index = children.indexOf(nodeName);
if(index==-1)
{
System.out.println("数据异常");
}
else if(index==0)
{
return;
}
else
{
//需要监听前一个节点的变化
waitPath="/locks/"+children.get(index-1);
zooKeeper.getData(waitPath,true,null);
//等待监听
waitLatch.await();
//监听结束,return
return;
}
}
}
//解锁
public void zkunlock() throws InterruptedException, KeeperException {
//删除结点
zooKeeper.delete(currentMode,-1);
}
}
测试代码:
package com.atguigu.zk.case2;
public class DistributeLockTest {
public static void main(String[] args) throws Exception {
DistributeLock lock1= new DistributeLock();
DistributeLock lock2 = new DistributeLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock1.zklock();
System.out.println("线程1启动,获取到锁");
Thread.sleep(5*1000);
lock1.zkunlock();
System.out.println("线程1释放锁");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
lock2.zklock();
System.out.println("线程2启动,获取到锁");
Thread.sleep(5*1000);
lock2.zkunlock();
System.out.println("线程2释放锁");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
运行结果:
Curator框架实现分布式锁
添加依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.3.0</version>
</dependency>
代码部分:
package com.atguigu.zk.case3;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class CuratorLockTest {
public static void main(String[] args) {
//创建分布式锁1
InterProcessMutex lock1 = new InterProcessMutex(getCuratorFramework(), "/locks");
//创建分布式锁2
InterProcessMutex lock2=new InterProcessMutex(getCuratorFramework(),"/locks");
new Thread(new Runnable() {
@Override
public void run() {
try{
lock1.acquire();
System.out.println("线程1获取到锁");
lock1.acquire();
System.out.println("线程1再次获取到锁");
Thread.sleep(5*1000);
lock1.release();
System.out.println("线程1释放锁");
lock1.release();
System.out.println("线程1再次释放锁");
}catch (Exception e)
{
System.out.println(e);
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try{
lock2.acquire();
System.out.println("线程2获取到锁");
lock2.acquire();
System.out.println("线程2再次获取到锁");
Thread.sleep(5*1000);
lock2.release();
System.out.println("线程2释放锁");
lock2.release();
System.out.println("线程2再次释放锁");
}catch (Exception e)
{
System.out.println(e);
}
}
}).start();
}
private static CuratorFramework getCuratorFramework() {
//重试的时间和次数
ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(3000, 3);
//创建zookeeper客户端
CuratorFramework client = CuratorFrameworkFactory.builder().connectString("hadoop102:2181,hadoop103:2181,hadoop104:2181")
.connectionTimeoutMs(2000)
.sessionTimeoutMs(2000)
.retryPolicy(exponentialBackoffRetry).build();
//客户端启动
client.start();
System.out.println("zookeeper启动成功");
return client;
}
}
运行结果: