zookeeper系列之【IdGenerator,简单原理】
zookeeper系列之【IdGenerator,多线程测试】
原理
见:zookeeper实现IdGenerator(原理版本)
代码实现
public interface IGenerator {
/**
* 生成器抽象方法
*/
long gen();
}
public class IdGenerator implements IGenerator {
private ZkClient client; // 客户端持有
private String nodePath; // 生成的顺序节点要放在哪个目录下
private ArrayBlockingQueue<String> removeQueue;
public IdGenerator(ZkClient client, String basePath, ArrayBlockingQueue<String> removeQueue) {
this.client = client;
this.nodePath = basePath.concat("/");
this.removeQueue = removeQueue;
// 初始化的时候,看看基础目录有没有,没有就来一个
if (!client.exists(basePath)) {
client.createPersistent(basePath, true);
}
}
@Override
public long gen() {
// 生成临时节点,zookeeper会话关闭时,这些节点自动消失
String fullPath = client.createEphemeralSequential(nodePath, null);
removeQueue.add(fullPath);// 添加到删除队列(如果正式用的话,client会话是不会轻易close的,需要异步线程来删除)
return Long.parseLong(fullPath.substring(fullPath.lastIndexOf("/") + 1));// 数字转换下
}
}
public class TestClient {
private static final int TOTAL_NUM = 10000;
private static final int THREAD_NUM = 10;
public static void main(String[] args) throws InterruptedException {
// 删除队列
ArrayBlockingQueue<String> removeQueue = new ArrayBlockingQueue<>(100000);
// 线程池
ExecutorService executorService = new ThreadPoolExecutor(10, 100, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(200), new ThreadFactory() {
private final AtomicInteger threadNum = new AtomicInteger(0);
@Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable, "pool-1-thread-" + threadNum.incrementAndGet());
}
});
CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM + 1);
// 启动异步删除线程
executorService.execute(new Runnable() {
private ZkClient deleteClient = new ZkClient("localhost:2181,localhost:2182,localhost:2183", 5000, 5000, new SerializableSerializer());
@Override
public void run() {
while (true) {// 只是演示
String removeNode = removeQueue.poll();
if (removeNode == null) {
if (countDownLatch.getCount() == 1) {// 退出判断
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
deleteClient.delete(removeNode);
}
countDownLatch.countDown();
}
});
final long start = System.currentTimeMillis();
for (int i = 0; i < THREAD_NUM; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
ZkClient client = new ZkClient("localhost:2181,localhost:2182,localhost:2183", 5000, 5000, new SerializableSerializer());
IGenerator generator = new IdGenerator(client, "/mygen", removeQueue);
for (int i = 0; i < TOTAL_NUM / THREAD_NUM; i++) { // 每个线程均匀分配下任务
System.out.println(generator.gen());
}
client.close();// 关闭ZK会话
countDownLatch.countDown();
if (countDownLatch.getCount() == 1) {// 统计时间
System.out.println("generator " + TOTAL_NUM + ", use time:" + (System.currentTimeMillis() - start));
}
}
});
}
countDownLatch.await();
// 关闭线程池
executorService.shutdown();
}
}