The following briefly introduces the application and principle of using Curator to implement zk distributed lock.
1. Connect the Factory class of zk
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; //Construct the global zk link object 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. Simulate multiple threads to compete for locks
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();//It will block until the lock is acquired successfully boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//Get the lock successfully or block for a certain time and return if(locked){ System.out.println(this.getName()+"Successful lock acquisition"); Thread.sleep(3000); }else{ System.out.println(this.getName()+"Failed to acquire lock"); } } catch (Exception e) { }finally{ try { lock.release(); System.out.println(this.getName()+"release lock successful"); } catch (Exception e) { } } } }
3. Test
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. Print the result:
Thread-2 acquires the lock successfully
Thread-1 failed to acquire lock
Thread-3 failed to acquire lock
Thread-2 released the lock successfully
5. If the locked code is replaced:
Bundle
boolean locked= lock.acquire(2000, TimeUnit.MILLISECONDS);//Get the lock successfully or block for a certain time and return if(locked){ System.out.println(this.getName()+"Successful lock acquisition"); Thread.sleep(3000); }else{ System.out.println(this.getName()+"Failed to acquire lock"); }
Replace with:
lock.acquire();//It will block until the lock is acquired successfully System.out.println(this.getName()+"Successful lock acquisition"); Thread.sleep(3000);
The print result is as follows:
Thread-3 acquires the lock successfully
Thread-3 released the lock successfully
Thread-2 acquires the lock successfully
Thread-2 released the lock successfully
Thread-1 acquires the lock successfully
Thread-1 released the lock successfully
It can be seen that all three threads can acquire the lock sequentially. So which method to use depends on your usage scenario.