首页 > 其他分享 >zookeeper分布式锁代码实现

zookeeper分布式锁代码实现

时间:2023-02-20 19:03:55浏览次数:42  
标签:Thread 代码 zookeeper ZKDistributedLock 线程 shared null 分布式

package com.boe.lock;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 自定义分布式锁
 */
public class ZKDistributedLock implements Watcher {

    private int threadId;
    //形如[第i个线程]
    private String THREAD_FLAG;
    //连接zookeeper服务器用
    private ZooKeeper zk = null;

    //分布式锁相关父节点路径
    private static final String GROUP_PATH = "/shared";
    //分布式锁相关的子节点路径
    private static final String SUB_PATH = "/shared/node";

    //当前临时顺序子节点
    private String currentEphemeralNode;
    //比当前临时顺序子节点序号小的前面那个子节点
    private String preEphemeralNode;


    //打印日志相关
    private static final Logger logger = Logger.getLogger(ZKDistributedLock.class);

    //使用闭锁,必须计数为0,await方法才解除阻塞继续向下执行
    private CountDownLatch connectCountDownLatch = new CountDownLatch(1);

    //使用闭锁,应对10个线程都抢到锁并处理完逻辑后,打印结果
    public static final CountDownLatch threadCountDownLatch = new CountDownLatch(5);

    //记录process方法使用次数
    private int count=0;


    /**
     * 构造方法
     */
    public ZKDistributedLock(int threadId) {
        this.threadId = threadId;
        THREAD_FLAG = "[第" + threadId + "个线程]";
    }


    /**
     * 回调函数,返回连接结果
     *
     * @param event
     */
    @Override
    public void process(WatchedEvent event) {
        if (event == null) {
            return;
        }
        //一种跟连接相关
        Event.KeeperState connectState = event.getState();
        //一种跟事件类型相关,如获取锁的线程删除临时节点,释放锁
        Event.EventType eventType = event.getType();
        //必须同时满足两个条件,闭锁才能减1
        if (connectState == Event.KeeperState.SyncConnected && eventType == Event.EventType.None) {
            //连接zookeeper成功
            logger.info(THREAD_FLAG + "连接zookeeper服务器成功");
            //闭锁减一
            connectCountDownLatch.countDown();
        } else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(preEphemeralNode)) {
            logger.info(THREAD_FLAG+"当前节点"+currentEphemeralNode+"前面节点"+preEphemeralNode+"被删除");
            try {
                if (isMinPath()) {
                    getDistributedLock();
                }
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else if (Event.KeeperState.Disconnected == connectState) {
            logger.info(THREAD_FLAG + "与zookeeper服务器断开连接");
        } else if (Event.KeeperState.AuthFailed == connectState) {
            logger.info(THREAD_FLAG + "权限检查失败");
        } else if (Event.KeeperState.Expired == connectState) {
            logger.info(THREAD_FLAG + "与zookeeper服务器会话失效");
        }

        System.out.println(THREAD_FLAG+"执行"+(++count)+"次process方法");


    }

    /**
     * 创建跟zookeeper服务器的连接
     *
     * @param connectAddress zookeeper服务器地址
     * @param sessionTimeout session超时时间
     */
    public void createConnection(String connectAddress, int sessionTimeout) throws IOException, InterruptedException {
        zk = new ZooKeeper(connectAddress, sessionTimeout, this);
        System.out.println(THREAD_FLAG+"开始连接zookeeper...");
        connectCountDownLatch.await();
        //回调函数闭锁归零,才打印
        //System.out.println("连接zookeeper成功!");
    }

    /**
     * 创建组路径
     */
    public void createGroupPath() throws KeeperException, InterruptedException {
        //zookeeper中不存在就创建
        if (zk.exists(GROUP_PATH, true) == null) {
            String createdPath = zk.create(GROUP_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            logger.warn(THREAD_FLAG + "创建" + createdPath + "成功");
        }

    }

    /**
     * 尝试获取锁
     */
    public void grabLock() throws KeeperException, InterruptedException {
        //先创建临时节点
        currentEphemeralNode = zk.create(SUB_PATH, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        logger.info(THREAD_FLAG + "创建" + currentEphemeralNode+"临时顺序节点");
        //检查是否可以获取锁
        if (isMinPath()) {
            //如果是最小序号的节点,获取锁
            getDistributedLock();
        }
    }


    /**
     * 判断当前临时节点是否是最小序号的,如果不是最小节点,获取前面节点,并且设置监听
     * @return
     */
    private boolean isMinPath() throws KeeperException, InterruptedException {
        //获取所有节点,并且排序
        List<String> nodes = zk.getChildren(GROUP_PATH, false);
        Collections.sort(nodes);
        //判断当前创建的临时顺序节点是否是序号为0的,是0就是最小,可以获取锁
        String node = currentEphemeralNode.substring(GROUP_PATH.length() + 1);//形如node0000?
        int index = nodes.indexOf(node);
        switch (index) {
            case -1:
                logger.info(THREAD_FLAG + "本节点不存在了" + node);
                return false;
            case 0:
                logger.info(THREAD_FLAG +node+"就是最小的子节点");
                return true;
            default:
                try {
                    //找到比自己序号小1的临时节点
                    preEphemeralNode = GROUP_PATH + "/" + nodes.get(index - 1);
                    logger.info(THREAD_FLAG + currentEphemeralNode + "前面的节点是" + preEphemeralNode);
                    //通过查询节点数据来设置监听
                    zk.getData(preEphemeralNode, true, new Stat());
                    return false;
                } catch (KeeperException e) {
                    if (zk.exists(preEphemeralNode, false) == null) {
                        logger.info(THREAD_FLAG + "排在" + currentEphemeralNode + "前面的子节点" + preEphemeralNode + "不存在");
                        //出现异常,再次调用
                        return isMinPath();
                    } else {
                        throw e;
                    }
                }
        }
    }

    /**
     * 获取锁成功
     */
    private void getDistributedLock() throws KeeperException, InterruptedException {
        if (zk.exists(currentEphemeralNode, false) == null) {
            logger.info(THREAD_FLAG + "节点不存在");
            return;
        }
        logger.info(THREAD_FLAG + "获取锁成功");
        Thread.sleep(2000);
        System.out.println(THREAD_FLAG + "干完活了~~~");
        //删除临时节点,不考虑版本
        zk.delete(currentEphemeralNode, -1);
        logger.info(THREAD_FLAG+"节点"+currentEphemeralNode+"已删除");
        //释放与zookeeper服务器的连接
        if (zk != null) {
            zk.close();
        }
        logger.info(THREAD_FLAG + "释放了与zookeeper的连接");

        //闭锁减1
        threadCountDownLatch.countDown();

    }

}

zookeeper分布式锁代码实现_zookeeper
ZKDistributedLock类实现了Watcher接口,需重写proces方法,每个线程会执行代码里process方法2次,一次为连接zookeeper服务器成功会执行一次,一次为前一个设置Watcher监听的节点被删除后,监听到后会再次执行一次process方法,并且在process方法里完成判断是否序号最小节点(isMinPath方法)和抢占锁(getDistributedLock方法)业务逻辑。

另外,刚开始创建序号最小节点的线程,会先创建/shared父节点,因此它也会执行两次process方法,虽然也是两次但是和其他序号的子节点是走不同的路线。它会执行在grabLock方法里完成判断是否序号最小节点(isMinPath方法)和抢占锁(getDistributedLock方法)业务逻辑。

再写一个测试类,在main方法里创建5个线程,模拟5个client连接zookeeper服务器创建临时有序节点,完成抢占锁的逻辑。

package com.boe.lock;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

import java.util.concurrent.CountDownLatch;

/**
 * 测试zookeeper分布式锁
 */
public class TestZKDistributedLock {

    private int threadId;
    //连接zookeeper的地址
    private static final String CONNECT_ADDRESS="node01:2181,node02:2181,node03:2181";
    private static final int SESSION_TIMEOUT=30000;


    //打印日志相关
    private static final Logger logger=Logger.getLogger(TestZKDistributedLock.class);

    //主方法
    public static void main(String[] args) {
        BasicConfigurator.configure();
        //启动5个线程,模拟5个client连接zookeeper服务器,创建临时有序节点并抢占锁
        for (int i = 0; i < 5; i++) {
            //线程数从1开始
            int threadId=i+1;
            //启动线程
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //创建跟zookeeper服务器的连接
                        ZKDistributedLock lock=new ZKDistributedLock(threadId);
                        lock.createConnection(CONNECT_ADDRESS,SESSION_TIMEOUT);
                        System.out.println("[第"+threadId+"个线程]+"连接成功,准备开始创建临时有序节点和抢占锁");
                        //首先确认是否创建父节点/Shared,只能有一个线程创建成功,zookeeper只会让一个线程创建成功
                        //哪个线程先执行到这里,哪个线程就创建父节点
                        synchronized (ZKDistributedLock.threadCountDownLatch){
                            lock.createGroupPath();
                        }
                        //尝试获取分布式锁
                        lock.grabLock();
                    } catch (Exception e) {
                        logger.error("[第"+threadId+"个线程]抛出异常");
                        e.printStackTrace();
                    }
                }
            }).start();
        }
        //循环结束,提示所有线程执行完成
        try {
            ZKDistributedLock.threadCountDownLatch.await();
            logger.info("所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

测试结果

启动zookeeper服务器,IDEA中本地运行,通过查看控制台日志记录,以及连接zookeeper服务器查看节点下子节点情况,发现正常的执行了创建临时有序节点、判断是否是最小节点、在前一个节点设置Watcher监听、抢占锁、释放锁的业务。

IDEA中控制台中结果

# 模拟5个client连接zookeeper服务器
[第5个线程]开始连接zookeeper...
[第1个线程]开始连接zookeeper...
[第2个线程]开始连接zookeeper...
[第4个线程]开始连接zookeeper...
[第3个线程]开始连接zookeeper...
# 5个线程均连接成功,都会执行一次process方法
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第5个线程]连接zookeeper服务器成功
264 [Thread-4-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]连接zookeeper服务器成功
[第5个线程]执行1次process方法
[第5个线程]连接成功,准备开始创建临时有序节点和抢占锁
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第3个线程]连接zookeeper服务器成功
264 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]连接zookeeper服务器成功
[第3个线程]执行1次process方法
[第3个线程]连接成功,准备开始创建临时有序节点和抢占锁
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第4个线程]连接zookeeper服务器成功
264 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]连接zookeeper服务器成功
[第4个线程]执行1次process方法
[第4个线程]连接成功,准备开始创建临时有序节点和抢占锁
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第2个线程]连接zookeeper服务器成功
264 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]连接zookeeper服务器成功
[第2个线程]执行1次process方法
[第2个线程]连接成功,准备开始创建临时有序节点和抢占锁
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(74) -[第1个线程]连接zookeeper服务器成功
264 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]连接zookeeper服务器成功
[第1个线程]执行1次process方法
[第1个线程]连接成功,准备开始创建临时有序节点和抢占锁
# 创建/shared父节点的线程,会再次执行一次process方法,它也将创建最小序号的临时有序节点
[第5个线程]执行2次process方法
323 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038051,0  request:: '/shared,,v{s{31,s{'world,'anyone}}},0  response:: '/shared 
2020-08-30 14:50:02 [ WARN] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(122) -[第5个线程]创建/shared成功
323 [Thread-4] WARN com.kaikeba.lock.ZKDistributedLock  - [第5个线程]创建/shared成功
340 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 3,1  replyHeader:: 3,257698038052,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000000 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第5个线程]创建/shared/node0000000000临时顺序节点
340 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]创建/shared/node0000000000临时顺序节点
344 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038052,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,1,0,0,0,1,257698038052} 
364 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 4,8  replyHeader:: 4,257698038052,0  request:: '/shared,F  response:: v{'node0000000000} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第5个线程]node0000000000就是最小的子节点
365 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]node0000000000就是最小的子节点
369 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038053,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000001 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第1个线程]创建/shared/node0000000001临时顺序节点
369 [Thread-0] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]创建/shared/node0000000001临时顺序节点
369 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 5,3  replyHeader:: 5,257698038053,0  request:: '/shared/node0000000000,F  response:: s{257698038052,257698038052,1598770202930,1598770202930,0,0,0,176833595994013721,0,0,257698038052} 
369 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038053,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,2,0,0,0,2,257698038053} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第5个线程]获取锁成功
370 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]获取锁成功
376 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038053,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,2,0,0,0,2,257698038053} 
380 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038053,0  request:: '/shared,F  response:: v{'node0000000000,'node0000000001} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第1个线程]/shared/node0000000001前面的节点是/shared/node0000000000
380 [Thread-0] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]/shared/node0000000001前面的节点是/shared/node0000000000
383 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038054,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000002 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第2个线程]创建/shared/node0000000002临时顺序节点
383 [Thread-1] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]创建/shared/node0000000002临时顺序节点
384 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 1,3  replyHeader:: 1,257698038054,0  request:: '/shared,T  response:: s{257698038051,257698038051,1598770202917,1598770202917,0,3,0,0,0,3,257698038054} 
391 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038055,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000000,'node0000000001} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第2个线程]/shared/node0000000002前面的节点是/shared/node0000000001
391 [Thread-1] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]/shared/node0000000002前面的节点是/shared/node0000000001
392 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038055,0  request:: '/shared/node0000000000,T  response:: ,s{257698038052,257698038052,1598770202930,1598770202930,0,0,0,176833595994013721,0,0,257698038052} 
397 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038055,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000003 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第4个线程]创建/shared/node0000000003临时顺序节点
397 [Thread-3] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]创建/shared/node0000000003临时顺序节点
400 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000001,T  response:: ,s{257698038053,257698038053,1598770202953,1598770202953,0,0,0,176833595994013718,0,0,257698038053} 
400 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 2,1  replyHeader:: 2,257698038056,0  request:: '/shared/node,,v{s{31,s{'world,'anyone}}},3  response:: '/shared/node0000000004 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(133) -[第3个线程]创建/shared/node0000000004临时顺序节点
400 [Thread-2] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]创建/shared/node0000000004临时顺序节点
404 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038055,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000000,'node0000000001} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第4个线程]/shared/node0000000003前面的节点是/shared/node0000000002
404 [Thread-3] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]/shared/node0000000003前面的节点是/shared/node0000000002
408 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000002,T  response:: ,s{257698038054,257698038054,1598770202976,1598770202976,0,0,0,176833595994013720,0,0,257698038054} 
408 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 3,8  replyHeader:: 3,257698038056,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004,'node0000000000,'node0000000001} 
2020-08-30 14:50:02 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(164) -[第3个线程]/shared/node0000000004前面的节点是/shared/node0000000003
408 [Thread-2] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]/shared/node0000000004前面的节点是/shared/node0000000003
411 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 4,4  replyHeader:: 4,257698038056,0  request:: '/shared/node0000000003,T  response:: ,s{257698038055,257698038055,1598770202981,1598770202981,0,0,0,248891189975973914,0,0,257698038055} 
# 序号最小的节点对应线程执行完逻辑,将释放分布式锁
[第5个线程]干完活了~~~
2377 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940016
2377 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000000 for sessionid 0x2743d37f9940016
2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第1个线程]当前节点/shared/node0000000001前面节点/shared/node0000000000被删除
2378 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]当前节点/shared/node0000000001前面节点/shared/node0000000000被删除
2378 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 6,2  replyHeader:: 6,257698038057,0  request:: '/shared/node0000000000,-1  response:: null
2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第5个线程]节点/shared/node0000000000已删除
2379 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]节点/shared/node0000000000已删除
2379 [Thread-4] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940019
2379 [Thread-4] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940019
2385 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038057,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004,'node0000000001} 
2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第1个线程]node0000000001就是最小的子节点
2385 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]node0000000001就是最小的子节点
2387 [Thread-4-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940019, packet:: clientPath:null serverPath:null finished:false header:: 7,-11  replyHeader:: 7,257698038058,0  request:: null response:: null
2387 [Thread-4] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940019
2020-08-30 14:50:04 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940019 closed
2387 [Thread-4] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940019 closed
2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第5个线程]释放了与zookeeper的连接
2388 [Thread-4] INFO com.kaikeba.lock.ZKDistributedLock  - [第5个线程]释放了与zookeeper的连接
2020-08-30 14:50:04 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940019
2390 [Thread-4-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940019
2393 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038058,0  request:: '/shared/node0000000001,F  response:: s{257698038053,257698038053,1598770202953,1598770202953,0,0,0,176833595994013718,0,0,257698038053} 
2020-08-30 14:50:04 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第1个线程]获取锁成功
2394 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]获取锁成功
[第1个线程]干完活了~~~
4402 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940018
4403 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000001 for sessionid 0x2743d37f9940018
2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第2个线程]当前节点/shared/node0000000002前面节点/shared/node0000000001被删除
4403 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]当前节点/shared/node0000000002前面节点/shared/node0000000001被删除
4403 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038059,0  request:: '/shared/node0000000001,-1  response:: null
2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第1个线程]节点/shared/node0000000001已删除
4403 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]节点/shared/node0000000001已删除
4404 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940016
4404 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940016
4405 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038059,0  request:: '/shared,F  response:: v{'node0000000002,'node0000000003,'node0000000004} 
2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第2个线程]node0000000002就是最小的子节点
4406 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]node0000000002就是最小的子节点
4408 [Thread-0-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940016, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038060,0  request:: null response:: null
4408 [Thread-0-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940016
2020-08-30 14:50:06 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940016 closed
4408 [Thread-0-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940016 closed
2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第1个线程]释放了与zookeeper的连接
4409 [Thread-0-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第1个线程]释放了与zookeeper的连接
# 刚开始不是最小序号的节点,需要在再次执行process方法里抢占锁
[第1个线程]执行2次process方法
2020-08-30 14:50:06 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940016
4409 [Thread-0-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940016
4410 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038060,0  request:: '/shared/node0000000002,F  response:: s{257698038054,257698038054,1598770202976,1598770202976,0,0,0,176833595994013720,0,0,257698038054} 
2020-08-30 14:50:06 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第2个线程]获取锁成功
4410 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]获取锁成功
[第2个线程]干完活了~~~
6414 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x3743d37f63e001a
6414 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000002 for sessionid 0x3743d37f63e001a
6415 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038061,0  request:: '/shared/node0000000002,-1  response:: null
2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第2个线程]节点/shared/node0000000002已删除
6415 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]节点/shared/node0000000002已删除
6415 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940018
6415 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940018
2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第4个线程]当前节点/shared/node0000000003前面节点/shared/node0000000002被删除
6418 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]当前节点/shared/node0000000003前面节点/shared/node0000000002被删除
6420 [Thread-1-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940018, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038062,0  request:: null response:: null
6420 [Thread-1-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940018
2020-08-30 14:50:08 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940018 closed
6420 [Thread-1-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940018 closed
2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第2个线程]释放了与zookeeper的连接
6420 [Thread-1-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第2个线程]释放了与zookeeper的连接
[第2个线程]执行2次process方法
2020-08-30 14:50:08 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940018
6421 [Thread-1-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940018
6422 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038062,0  request:: '/shared,F  response:: v{'node0000000003,'node0000000004} 
2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第4个线程]node0000000003就是最小的子节点
6422 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]node0000000003就是最小的子节点
6425 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038062,0  request:: '/shared/node0000000003,F  response:: s{257698038055,257698038055,1598770202981,1598770202981,0,0,0,248891189975973914,0,0,257698038055} 
2020-08-30 14:50:08 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第4个线程]获取锁成功
6425 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]获取锁成功
[第4个线程]干完活了~~~
8433 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got notification sessionid:0x2743d37f9940017
8434 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Got WatchedEvent state:SyncConnected type:NodeDeleted path:/shared/node0000000003 for sessionid 0x2743d37f9940017
2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(78) -[第3个线程]当前节点/shared/node0000000004前面节点/shared/node0000000003被删除
8434 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]当前节点/shared/node0000000004前面节点/shared/node0000000003被删除
8434 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038063,0  request:: '/shared/node0000000003,-1  response:: null
2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第4个线程]节点/shared/node0000000003已删除
8434 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]节点/shared/node0000000003已删除
8434 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x3743d37f63e001a
8434 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x3743d37f63e001a
8436 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 5,8  replyHeader:: 5,257698038063,0  request:: '/shared,F  response:: v{'node0000000004} 
2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(158) -[第3个线程]node0000000004就是最小的子节点
8436 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]node0000000004就是最小的子节点
8439 [Thread-3-SendThread(node03:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x3743d37f63e001a, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038064,0  request:: null response:: null
8439 [Thread-3-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x3743d37f63e001a
8439 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 6,3  replyHeader:: 6,257698038064,0  request:: '/shared/node0000000004,F  response:: s{257698038056,257698038056,1598770202989,1598770202989,0,0,0,176833595994013719,0,0,257698038056} 
2020-08-30 14:50:10 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x3743d37f63e001a closed
8439 [Thread-3-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x3743d37f63e001a closed
2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第4个线程]释放了与zookeeper的连接
8440 [Thread-3-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第4个线程]释放了与zookeeper的连接
[第4个线程]执行2次process方法
2020-08-30 14:50:10 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x3743d37f63e001a
8440 [Thread-3-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x3743d37f63e001a
2020-08-30 14:50:10 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(188) -[第3个线程]获取锁成功
8440 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]获取锁成功
[第3个线程]干完活了~~~
10452 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 7,2  replyHeader:: 7,257698038065,0  request:: '/shared/node0000000004,-1  response:: null
2020-08-30 14:50:12 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(193) -[第3个线程]节点/shared/node0000000004已删除
10453 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]节点/shared/node0000000004已删除
10454 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ZooKeeper  - Closing session: 0x2743d37f9940017
10454 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Closing client for session: 0x2743d37f9940017
10468 [Thread-2-SendThread(node02:2181)] DEBUG org.apache.zookeeper.ClientCnxn  - Reading reply sessionid:0x2743d37f9940017, packet:: clientPath:null serverPath:null finished:false header:: 8,-11  replyHeader:: 8,257698038066,0  request:: null response:: null
10468 [Thread-2-EventThread] DEBUG org.apache.zookeeper.ClientCnxn  - Disconnecting client for session: 0x2743d37f9940017
2020-08-30 14:50:13 [ INFO] - org.apache.zookeeper.ZooKeeper -ZooKeeper.java(693) -Session: 0x2743d37f9940017 closed
10468 [Thread-2-EventThread] INFO org.apache.zookeeper.ZooKeeper  - Session: 0x2743d37f9940017 closed
2020-08-30 14:50:13 [ INFO] - com.kaikeba.lock.ZKDistributedLock -ZKDistributedLock.java(198) -[第3个线程]释放了与zookeeper的连接
10468 [Thread-2-EventThread] INFO com.kaikeba.lock.ZKDistributedLock  - [第3个线程]释放了与zookeeper的连接
[第3个线程]执行2次process方法
2020-08-30 14:50:13 [ INFO] - org.apache.zookeeper.ClientCnxn -ClientCnxn.java(522) -EventThread shut down for session: 0x2743d37f9940017
10469 [Thread-2-EventThread] INFO org.apache.zookeeper.ClientCnxn  - EventThread shut down for session: 0x2743d37f9940017
2020-08-30 14:50:13 [ INFO] - com.kaikeba.lock.TestZKDistributedLock -TestZKDistributedLock.java(55) -所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑
10470 [main] INFO com.kaikeba.lock.TestZKDistributedLock  - 所有线程创建临时有序节点完成,并完成抢占锁后执行业务逻辑
(2)连接zookeeper服务器查看子节点结果

# IDEA中本地启动5个线程后,创建了父节点/shared,且创建了临时有序子节点
[zk: node01:2181(CONNECTED) 104] ls /shared
[node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
[zk: node01:2181(CONNECTED) 105] ls /shared
[node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
[zk: node01:2181(CONNECTED) 106] ls /shared
[node0000000002, node0000000003, node0000000004, node0000000000, node0000000001]
[zk: node01:2181(CONNECTED) 107] ls /shared
[node0000000002, node0000000003, node0000000004, node0000000001]
[zk: node01:2181(CONNECTED) 108] ls /shared
[node0000000002, node0000000003, node0000000004, node0000000001]
[zk: node01:2181(CONNECTED) 109] ls /shared
[node0000000002, node0000000003, node0000000004]
[zk: node01:2181(CONNECTED) 110] ls /shared
[node0000000002, node0000000003, node0000000004]
[zk: node01:2181(CONNECTED) 111] ls /shared
[node0000000003, node0000000004]
[zk: node01:2181(CONNECTED) 112] ls /shared
[node0000000003, node0000000004]
[zk: node01:2181(CONNECTED) 113] ls /shared
[node0000000003, node0000000004]
[zk: node01:2181(CONNECTED) 114] ls /shared
[node0000000004]
[zk: node01:2181(CONNECTED) 115] ls /shared
[node0000000004]
[zk: node01:2181(CONNECTED) 116] ls /shared
[node0000000004]
[zk: node01:2181(CONNECTED) 117] ls /shared
[]

标签:Thread,代码,zookeeper,ZKDistributedLock,线程,shared,null,分布式
From: https://blog.51cto.com/u_15973676/6069323

相关文章

  • zookeeper都有哪些使用场景?
    一、分布式协调这个其实是zookeeper很经典的一个用法,简单来说,就好比,你A系统发送个请求到MQ,然后B系统消费之后处理了。那么A系统如何知道B系统的处理结果?用zookeeper就......
  • 那些一行代码实现的神奇功能
    一行代码修改网页任意内容以前改网页内容,你可能直接修改源代码,但知道了下面这个命令,打开浏览器,在Console中输入document.body.contentEditable='true';一行代码启动W......
  • 分布式锁用 Redis 还是 Zookeeper?
    为什么用分布式锁?在讨论这个问题之前,我们先来看一个业务场景:系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查......
  • zookeeper的入门
    zookeeper是一个分布式服务框架,是ApacheHadoop的一个子项目,它主要是来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务,状态同步服务,集群管理,分布式应用配置......
  • 代码随想录算法训练营Day18 二叉树|  654.最大二叉树  617.合并二叉树  700.二叉搜
    654.最大二叉树题目链接:654.最大二叉树给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最......
  • Zookeeper-ZKFC的原理和功能
    一、前言HADOOP2HA架构引入了ZKFC、Journalnode组件,本篇文章主要介绍ZKFC的功能和原理。HA架构支持两种切换方式:手动切换: 通过命令实现主备之间的切换,可以用HDFS升......
  • 1688商品列表数据采集接口(商品销量,商品属性接口,商品优惠券接口)代码展示
    简介:item_search-按关键字搜索商品接口,调用该接口可以拿到商品ID,商品标题,商品优惠券,商品到手价,商品价格,商品优惠价,商品sku属性,商品图片,商品视频,商品sku属性图片,商品属性描述......
  • 简述7个流行的强化学习算法及代码实现!
    目前流行的强化学习算法包括Q-learning、SARSA、DDPG、A2C、PPO、DQN和TRPO。这些算法已被用于在游戏、机器人和决策制定等各种应用中,并且这些流行的算法还在不断发展......
  • Filter_案例1_登录验证_代码实现与Filter_案例2_过滤敏感词汇_分析
    Filter_案例1_登录验证_代码实现     重新打开一个新导航栏:     切换一个浏览器再打开:   packagehf.xueqiang.web.filter;importj......
  • OpenHarmony 分布式相机(上)
    作者:徐金生最近陆续看到各社区上有关OpenHarmony媒体相机的使用开发文档,相机对于富设备来说必不可少,日常中我们经常使用相机完成拍照、人脸验证等OpenHarmony系统一个重要......