以下简单介绍使用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个线程都可以顺序的获得到锁。所以具体使用哪个方法,需要看你的使用场景。