4. Zookeeper 示例

1. 分布式锁

创建临时节点实现分布式锁,实现的是独占锁。

public interface Lock {
    void lock();

    void unlock();
}

public abstract class ZkAbstractLock implements Lock {

    private static String connectStr = "192.168.67.139:2184";

    public static String path = "/lock";

    protected ZkClient client = new ZkClient(connectStr);

    @Override
    public void lock() {
        if (tryLock()) {
            System.out.println(Thread.currentThread().getName() + "--->获取锁成功!");
        } else {
            waitForLock();
            lock();
        }
    }

    protected abstract boolean tryLock();

    protected abstract void waitForLock();

    @Override
    public void unlock() {
        client.close();
    }
}

public class ZkLockImpl extends ZkAbstractLock {

    private CountDownLatch cdl = null;

    @Override
    protected boolean tryLock() {
        try {
            client.createEphemeral(path);
            return true;
        } catch (ZkException e) {
            return false;
        }
    }

    @Override
    protected void waitForLock() {
        IZkDataListener iZkDataListener = new IZkDataListener() {
            @Override
            public void handleDataChange(String dataPath, Object data) {

            }

            //一旦/lock节点被删除以后,就会触发这个方法
            @Override
            public void handleDataDeleted(String dataPath) {
                //让等待的代码不再等待了
                if (cdl != null) {
                    cdl.countDown();
                }
            }
        };
        //注册 Watcher
        client.subscribeDataChanges(path, iZkDataListener);

        if (client.exists(path)) {
            cdl = new CountDownLatch(1);
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //取消该客户端的订阅关系
        client.unsubscribeDataChanges(path, iZkDataListener);
    }
}

2. 分布式栅栏

public class BarrierDemo {
    private static String barrierPath = "/barrier";

    ZkClient zkClient = new ZkClient("192.168.67.139:2184");

    @Test
    public void test() throws InterruptedException {
        //核心思想是每个任务执行完成后,在节点上创建一个子节点,当子节点个数达到要求后,放行下一个任务
        init();
        for (int i = 0; i < 10; i++) {
            task("task" + i, new Random().nextInt(20));
        }
        monitor();
        Thread.currentThread().join();
    }

    private void init() {
        if (!zkClient.exists(barrierPath)) {
            zkClient.createPersistent(barrierPath, 10);
        }
        listener();
    }

    private void task(String nodeName, int loop) {
        CompletableFuture.runAsync(() -> {
            for (int i = 0; i < loop; i++) {
                System.out.println(nodeName + "-->" + (loop - i));
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("=========" + nodeName + "========任务完成,开始创建临时有序节点");
            zkClient.createEphemeralSequential(barrierPath + "/" + nodeName, "");
        });
    }

    private void monitor() throws InterruptedException {
        Integer nodeNum = zkClient.readData(barrierPath);
        while (true) {
            List<String> children = zkClient.getChildren(barrierPath);
            if (nodeNum == children.size()) {
                zkClient.createEphemeral(barrierPath + "/start", "");
                break;
            }
            TimeUnit.MILLISECONDS.sleep(100);
        }
    }

    private void listener() {
        zkClient.subscribeChildChanges(barrierPath + "/start", ((parentPath, currentChilds) -> {
            if (parentPath.equals(barrierPath + "/start")) {
                System.out.println("===========全部任务做完了=========");
                System.exit(1);
            }
        }));
    }
}

3. 分布式队列

public class FIFOQueue<T> {

    protected final ZkClient zkClient;

    protected final String root;

    protected static final String node_name = "n_";

    public FIFOQueue(ZkClient zkClient, String root) {
        this.root = root;
        this.zkClient = zkClient;
    }

    private int size() {
        return zkClient.getChildren(root).size();
    }

    private boolean isEmpty() {
        return zkClient.getChildren(root).size() == 0;
    }

    public boolean push(T data) {
        String nodePath = root.concat("/").concat(node_name);
        try {
            zkClient.createEphemeralSequential(nodePath, data);
            System.out.println(Thread.currentThread().getName() + "--> 成功push数据!!");
        } catch (ZkNoNodeException e) {
            zkClient.createPersistent(root);
            push(data);
        } catch (Exception e) {
            throw ExceptionUtil.convertToRuntimeException(e);
        }
        return true;
    }

    public T poll() {
        List<String> children = zkClient.getChildren(root);
        if (children.size() == 0) {
            return null;
        }
        Collections.sort(children, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return getNodeNumber(o1, node_name).compareTo(getNodeNumber(o2, node_name));
            }
        });

        try {
            String pollData = children.get(0);
            String fullPath = root.concat("/").concat(pollData);
            T data = (T) zkClient.readData(fullPath);
            zkClient.delete(fullPath);
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getNodeNumber(String string, String nodeName) {
        int index = string.lastIndexOf(nodeName);
        if (index >= 0) {
            index += node_name.length();
            return index <= string.length() ? string.substring(index) : "";
        }
        return string;
    }
}

4. 分布式 ID

public class Id {
    private static String connectStr = "192.168.67.139:2184";
    private final String root = "/ID";
    private final String nodeName = "/order";
    private ZkClient zkClient = null;
    private ExecutorService delExector = null;

    public Id() {
        init();
    }

    private void init() {
        zkClient = new ZkClient(connectStr, 5000);
        delExector = Executors.newFixedThreadPool(10);
        if (!zkClient.exists(root)) {
            zkClient.createPersistent(root);
        }
    }

    private String getId() {
        String nodePath = root.concat(nodeName);
        String ephemeralSequential = zkClient.createEphemeralSequential(nodePath, "");
        System.out.println(ephemeralSequential);

        delExector.execute(() -> zkClient.delete(ephemeralSequential));
        return getId(ephemeralSequential);
    }

    private void stop() {
        delExector.shutdown();
        try {
            delExector.awaitTermination(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (zkClient != null) {
            zkClient.close();
        }
    }

    private String getId(String str) {
        int index = str.lastIndexOf(nodeName);
        return str.substring(index + nodeName.length());
    }

    public static void main(String[] args) {
        Id id = new Id();
        System.out.println(id.getId());
        id.stop();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值