基于Zookeeper的分布式锁实现

来源:互联网 发布:申请淘宝达人的条件 编辑:程序博客网 时间:2024/05/19 00:13

基于zk的分布式锁实现


1、pom依赖的包

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ganymede</groupId><artifactId>zk-distributed-lock</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>zk-distributed-lock</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><zookeeper.version>3.4.5</zookeeper.version><curator.version>2.9.0</curator.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>${zookeeper.version}</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>${curator.version}</version></dependency></dependencies></project>


2、操作zk的工厂类

package com.ganymede.lock;import org.apache.curator.RetryPolicy;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.CuratorFrameworkFactory;import org.apache.curator.retry.ExponentialBackoffRetry;/** * 操作zk的工厂类 *  * @author Ganymede * */public class ZookeeperFactory {private static final String connectString = "spark1:2181,spark2:2181,spark3:2181";public static CuratorFramework curatorClient = null;public static CuratorFramework createClient() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);if (curatorClient != null) {return curatorClient;}curatorClient = CuratorFrameworkFactory.builder().connectString(connectString).retryPolicy(retryPolicy).sessionTimeoutMs(1000).connectionTimeoutMs(1000).build();curatorClient.start();return curatorClient;}}




3、模拟多线程时,出问题的程序代码块

package com.ganymede.lock;import java.util.concurrent.atomic.AtomicBoolean;/** * 模拟多线程时,出问题的程序代码块 * @author Ganymede * */public class LimitedResource {private final AtomicBoolean ab = new AtomicBoolean(false);public void useResource() throws InterruptedException {if (!ab.compareAndSet(false, true)) {throw new IllegalArgumentException("线程" + Thread.currentThread().getId() + "非法操作!");}System.out.println("线程" + Thread.currentThread().getId() + "正在操作");Thread.sleep(1000);ab.set(false);}}

4、zk分布式锁实现,不可重用锁

package com.ganymede.lock;import java.util.concurrent.TimeUnit;import org.apache.curator.framework.CuratorFramework;import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;/** * 不可重用锁  * 同一线程,不能两次调用acquire  * 不会同时拥有两把锁 *  * @author Ganymede * */public class ZkDistributedLock {private InterProcessSemaphoreMutex lock;private LimitedResource resource;private String threadName;public ZkDistributedLock(CuratorFramework client, String path, LimitedResource resource, String threadName) {lock = new InterProcessSemaphoreMutex(client, path);this.resource = resource;this.threadName = threadName;}public void execute(long time, TimeUnit unit) {// acquire(time, unit),获取到了锁返回true,有超时机制,在unit为单位的time中还没获取到锁,就超时了try {while (!lock.acquire(time, unit)) {System.out.println("线程" + threadName + Thread.currentThread().getId() + "正在着急等待获取锁");}System.out.println("线程" + threadName + Thread.currentThread().getId() + "获取锁");resource.useResource();System.out.println("线程" + threadName + Thread.currentThread().getId() + "释放锁");} catch (Exception e) {e.printStackTrace();} finally {try {// release()释放锁,获取到锁之后,完成了任务,必须释放lock.release();} catch (Exception e) {e.printStackTrace();}}}}


5、模似多线程并发操作

package com.ganymede.lock;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import org.apache.curator.framework.CuratorFramework;/** * 模似多线程并发操作 *  * @author Ganymede * */public class ZkDistributedLockTest {public static void main(String[] args) throws InterruptedException {final LimitedResource lr = new LimitedResource();final String path = "/ganymede/lock";ExecutorService service = Executors.newFixedThreadPool(7);for (int i = 0; i < 7; i++) {Callable<Void> task = new Callable<Void>() {@Overridepublic Void call() throws Exception {CuratorFramework client = ZookeeperFactory.createClient();ZkDistributedLock lock = new ZkDistributedLock(client, path, lr, "thread");lock.execute(5, TimeUnit.SECONDS);return null;}};service.submit(task);}service.shutdown();service.awaitTermination(25, TimeUnit.MINUTES);}}


6、运行结果

线程thread14获取锁线程14正在操作线程thread14释放锁线程thread15获取锁线程15正在操作线程thread15释放锁线程thread16获取锁线程16正在操作线程thread16释放锁线程thread12获取锁线程12正在操作线程thread12释放锁线程thread11获取锁线程11正在操作线程thread17正在着急等待获取锁线程thread13正在着急等待获取锁线程thread11释放锁线程thread17获取锁线程17正在操作线程thread17释放锁线程thread13获取锁线程13正在操作线程thread13释放锁
多线程抢占资源下,只有一个线程可以获得一次锁,并且不能两次获取。


7、查看zk下的目录



原创粉丝点击