Java实现分布式锁(模板设计模式+zk分布式锁+JUC精确唤醒+行锁效果)-修复一些问题

本文介绍了一种基于ZooKeeper的分布式锁实现方案,通过使用CountDownLatch来控制线程的等待与唤醒,确保了多线程环境下的资源访问同步。文章详细展示了DistributeZKLock类的trylock和waitlock方法,以及MyThread类如何利用这些方法执行业务逻辑。

之前的代码,细心的朋友发现一些问题,现在修复了这些问题(对每个线程,设置一个CountDownLatch)

package com.hollycrm;

import org.I0Itec.zkclient.ZkClient;

abstract class DistributeAbstractLock {

private static String ZKSERVER_ADDRESS = "localhost:2181";

protected static int SERVER_TIMEOUT = 45*1000;

protected ZkClient zkClient = new ZkClient(ZKSERVER_ADDRESS , SERVER_TIMEOUT);

protected String zkpath = "/zkpath";

public void lock(String id){
    if(trylock(id)){
        System.out.println("线程 :"+ Thread.currentThread().getName() + " 拿到锁");
    }else{
        waitlock(id);

        lock(id);
    }
}

public void unlock(String id){
    if(zkClient!=null ){
        //zkClient.delete(zkpath);
        zkClient.delete(id);//相当于客户端quit命令
        System.out.println("线程 :"+ Thread.currentThread().getName() + " 释放锁成功");
    }
}

public abstract boolean trylock(String id);

public abstract void waitlock(String id);

}

package com.hollycrm;

import org.I0Itec.zkclient.IZkDataListener;
import java.util.concurrent.*;

public class DistributeZKLock extends DistributeAbstractLock {

private CountDownLatch countDownLatch;

public boolean trylock(String id) {

    try {
        System.out.println("线程 :"+ Thread.currentThread().getName() + "尝试创建节点:"+ id);
        zkClient.createEphemeral(id);
        System.out.println("线程 :"+ Thread.currentThread().getName() + "创建节点:"+ id +"成功!");
        return true;
    } catch (Exception e) {
        System.out.println("线程 :"+ Thread.currentThread().getName() + "尝试创建节点:"+ id +"失败!");
        return false;
    }
}

public void waitlock(String id) {

    IZkDataListener iZkDataListener = new IZkDataListener() {
        public void handleDataChange(String s, Object o) throws Exception {

        }

        public void handleDataDeleted(String s) throws Exception {
            System.out.println("线程 :"+ Thread.currentThread().getName() + "感知到zk节点发生变化,阻塞线程即将被唤醒!");
                countDownLatch.countDown();
        }
    };

        if(zkClient.exists(id)){
        try {
            countDownLatch = new CountDownLatch(1);
            System.out.println("线程 :"+ Thread.currentThread().getName() + "即将进入阻塞状态!");
            countDownLatch.await(SERVER_TIMEOUT , TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

}

package com.hollycrm;

import com.hollycrm.service.OrderService;

public class MyThread implements Runnable {

private DistributeZKLock zkLock ;

private OrderService orderService;

private String id;

public MyThread(DistributeZKLock zkLock, OrderService orderService, String id) {
    this.zkLock = zkLock;
    this.orderService = orderService;
    this.id = id;
}

public void run() {

    zkLock.lock(id);

    try{
        System.out.println("线程 :"+ Thread.currentThread().getName() + " 执行业务逻辑");

        String order = orderService.createOrder();
        System.out.println("线程 :"+ Thread.currentThread().getName() + "生成订单号 :" + order);
    }finally {
        zkLock.unlock(id);
    }
}

}

package com.hollycrm.service;

public class OrderService {

public static int num;

public String createOrder(){

    return "生成订单" + (++num);

}

}

package com.hollycrm;

import com.hollycrm.service.OrderService;
import java.util.ArrayList;

public class Test {

public static void main(String[] args) {

    DistributeZKLock zkLock = new DistributeZKLock();

    OrderService orderService = new OrderService();
    OrderService orderService1 = new OrderService();

    ArrayList<MyThread> list = new ArrayList<MyThread>();
    ArrayList<MyThread> list1 = new ArrayList<MyThread>();

    for (int i = 0; i < 10; i++) {
        list.add(new MyThread(zkLock , orderService,"/lock1"));
    }
    /*for (int i = 0; i < 100; i++) {
        list.add(new MyThread(zkLock , orderService,"/lock2"));
    }*/
    for (int i = 0; i < 10; i++) {
        list1.add(new MyThread(zkLock , orderService1,"/lock1"));
    }
    /*for (int i = 0; i < 100; i++) {
        list1.add(new MyThread(zkLock , orderService1,"/lock4"));
    }*/

    for (int i = 0; i < 10; i++) {
        new Thread(list.get(i)).start();
        new Thread(list1.get(i)).start();
    }

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值