以下简单介绍使用Curator来实现zk分布式锁的应用和原理。
1.连接zk的Factory类
package com.zk;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class ZkClientFactory {
private static CuratorFramework client;
//构造全局的zk链接对象
public static CuratorFramework getInstance(String url){
if(null == client){
synchronized(ZkClientFactory.class){
if(null == client){
CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder();
client = builder.connectString(url)
.sessionTimeoutMs(3000)
.connectionTimeoutMs(3000)
.canBeReadOnly(false)
.retryPolicy(new ExponentialBackoffRetry(1000, Integer.MAX_VALUE))
.namespace(null)
.defaultData(null)
.build();
client.start();
}
}
}
return client;
}
}
2.模拟多个线程来竞争锁
class MyJob extends Thread{
CuratorFramework client;
public MyJob(CuratorFramework client){
this.client = client;
}
public void run(){
InterProcessMutex lock = new InterProcessMutex(client, "/test");
try {
//lock.acquire();//会一直阻塞到获得锁成功
boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//获得锁成功或阻塞一定时间返回
if(locked){
System.out.println(this.getName()+"获取锁成功");
Thread.sleep(3000);
}else{
System.out.println(this.getName()+"获取锁失败");
}
} catch (Exception e) {
}finally{
try {
lock.release();
System.out.println(this.getName()+"释放锁成功");
} catch (Exception e) {
}
}
}
}
3.测试
public class Lock {
private static final String ZK_ADDRESS = "127.0.0.1:2182";
private static CuratorFramework client = ZkClientFactory.getInstance(ZK_ADDRESS);
public static void main(String[] args){
MyJob jb1 = new MyJob(client);
MyJob jb2 = new MyJob(client);
MyJob jb3 = new MyJob(client);
jb1.start();
jb2.start();
jb3.start();
}
}
4.打印结果 :
Thread-2获取锁成功
Thread-1获取锁失败
Thread-3获取锁失败
Thread-2释放锁成功
5.假如把加锁的代码换掉:
把
boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//获得锁成功或阻塞一定时间返回
if(locked){
System.out.println(this.getName()+"获取锁成功");
Thread.sleep(3000);
}else{
System.out.println(this.getName()+"获取锁失败");
}
换为:
lock.acquire();//会一直阻塞到获得锁成功
System.out.println(this.getName()+"获取锁成功");
Thread.sleep(3000);
打印结果如下 :
Thread-3获取锁成功
Thread-3释放锁成功
Thread-2获取锁成功
Thread-2释放锁成功
Thread-1获取锁成功
Thread-1释放锁成功
可以看到,3个线程都可以顺序的获得到锁。所以具体使用哪个方法,需要看你的使用场景。