package com.alibaba.rocketmq.example.simple; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import com.alibaba.rocketmq.client.consumer.DefaultMQPullConsumer; import com.alibaba.rocketmq.client.exception.MQClientException; import com.alibaba.rocketmq.common.message.MessageQueue; public class ScheduleTopicTask implements Runnable { private final DefaultMQPullConsumer consumer; private final String topic; private final ExecutorService topicService; private final Object balanceChanged; public ScheduleTopicTask(DefaultMQPullConsumer consumer, String topic, ExecutorService topicService, Object balanceChanged) { this.topic = topic; this.consumer = consumer; this.topicService = topicService; this.balanceChanged = balanceChanged; } @Override public void run() { System.out.println("Begin to handle topic request: " + topic); for (;;) { // 使用这种方式,让多个consumer在多个分区之间进行负载均衡消费 // 订阅topic分区 CountDownLatch stopLatch = null; AtomicBoolean mqTaskRunning = null; boolean isErrorHappen = false; try { System.out.println("Begin to fetch mqs for topic : " + topic); Set<MessageQueue> topicMqs = consumer.fetchMessageQueuesInBalance(topic); System.out.println("finished to fetch mqs for topic : " + topic + " " + topicMqs); if (topicMqs.size() > 0) { stopLatch = new CountDownLatch(topicMqs.size()); mqTaskRunning = new AtomicBoolean(true); /* * TODO 这里不好,如果submit内部出错,会导致 一部分成功,一部分失败。最好避免 资源泄露 */ for (MessageQueue mq : topicMqs) { System.out.println("Begin to submit mq pull task for topic : " + topic + " " + mq); topicService.submit(new PullMsgFromMqTask(consumer, mq, mqTaskRunning, stopLatch)); } } else { // wait for a while to retry to get the mqs isErrorHappen = true; } } catch (MQClientException e) { isErrorHappen = true; e.printStackTrace(); } if (!isErrorHappen) { // wait for the notification that some changes happen for the queues. // need to rebalance the queues. try { System.out.println("Begin to wait mqs changed for topic : " + topic); this.balanceChanged.wait(); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("found mqs changed for topic : " + topic); // 1. stops the mq task mqTaskRunning.set(false); // 2. wait for the stopping, TODO use timeout try { stopLatch.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { // error happen, wait and retry try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }