登录
原创

java分布式锁zk实现

发布于 2020-12-03 阅读 503
  • Java
原创

传统单体项目情况下,要实现锁可直接通过java提供的关键字,或者工具类实现。但在分布式情况下,就需要借助外部工具,如redis,zk等。
下面介绍一种通过zk实现的分布式锁。

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 CuratorDemo {
 
	public static void main(String[] args) throws Exception {
		
		//操作失败重试机制 1000毫秒间隔 重试3次
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
		//创建Curator客户端
		CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.1.18:2181", retryPolicy);
		//开始
		client.start();
		
		/**
		 * 这个类是线程安全的,一个JVM创建一个就好
		 * mylock 为锁的根目录,我们可以针对不同的业务创建不同的根目录
		 */
		final InterProcessMutex lock = new InterProcessMutex(client, "/mylock");
	    try {
	    	//阻塞方法,获取不到锁线程会挂起。
	    	lock.acquire();
	    	System.out.println("已经获取到锁");
	    	 Thread.sleep(10000);
	    } catch (Exception e) {
			e.printStackTrace();
		}
	    finally{
	    	//释放锁,必须要放到finally里面,已确保上面方法出现异常时也能够释放锁。
	    	lock.release();
	    }
		
	    Thread.sleep(10000);
	    
		client.close();
	}
 
}


模拟多个客户端

public class CuratorDemo {
 
	public static void main(String[] args) throws Exception {
		for (int i = 0; i < 10; i++) {
			//启动10个线程模拟多个客户端
			Jvmlock jl = new Jvmlock(i);
			new Thread(jl).start();
			//这里加上300毫秒是为了让线程按顺序启动,不然有可能4号线程比3号线程先启动了,这样测试就不准了。
			Thread.sleep(300);
		}
	}
	
	public static class Jvmlock implements Runnable{
		
		private int num;
		public Jvmlock(int num) {
			this.num = num;
		}
		
		@Override
		public void run() {
			RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
			CuratorFramework client = CuratorFrameworkFactory
					.newClient("192.168.142.128:2181", retryPolicy);
			client.start();
			
			InterProcessMutex lock = new InterProcessMutex(client,
					"/mylock");
			try {
				System.out.println("我是第" + num + "号线程,我开始获取锁");
				lock.acquire();
				System.out.println("我是第" + num + "号线程,我已经获取锁");
				Thread.sleep(10000);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					lock.release();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			client.close();
		}
	}
 
}


打印结果
image.png

如果是要控制api接口的话,可以借助注解,aspect等方式进行控制。

https://blog.csdn.net/nimasike/article/details/51567653

评论区

咸鱼

0

0

0

举报