关于RabbitMQ的Channel默认线程(一个Connection控制线程数量)

前言

最近做了一个小功能,是通过一个客户端消费者监听队列消息, 代码如下:

Connection conn = getConnection();
Channel channel = conn.createChannel();
MessageConsumer consumer = ...
channel.basicConsume(realQueue, true, consumer);

通过jvm工具观察rabbitmq的线程使用情况,发现生产者每发一条消息,消费者这边就会创建一条线程,
言下之意,一个channel当消息来到时就会异步处理这些消息.

定位

通过断点查找发现原来是 ConsumerWorkService这个类控制的。
这个类顾名思义,就是消费者工作 ExecutorService, 这里的Service表示的是ExecutorService

这个类构造函数里有一个executor参数,当这个参数为空时,就会创建一个Executors.newFixedThreadPool,代码如下:

final public class ConsumerWorkService {
    private static final int MAX_RUNNABLE_BLOCK_SIZE = 16;
    private static final int DEFAULT_NUM_THREADS = Runtime.getRuntime().availableProcessors() * 2;
    private final ExecutorService executor;
    private final boolean privateExecutor;
    private final WorkPool<Channel, Runnable> workPool;
    private final int shutdownTimeout;

    public ConsumerWorkService(ExecutorService executor, ThreadFactory threadFactory, int queueingTimeout, int shutdownTimeout) {
        this.privateExecutor = (executor == null);
        this.executor = (executor == null) ? Executors.newFixedThreadPool(DEFAULT_NUM_THREADS, threadFactory)
                                           : executor;
        this.workPool = new WorkPool<>(queueingTimeout);
        this.shutdownTimeout = shutdownTimeout;
    }
  ...

默认的executor 会使用 CPU核数的2倍 作为线程池里线程的数量。

所以到底是要用多个channel,还是单个channel,这个就是其中一个参考依据。

这个executor又是怎么传进来的呢?

答案:

ConnectionFactory -> AMQConnection -> ChannelManager -> ConsumerWorkService

ConnectionFactory有一个属性是 shareExecutorService ,这个属性表示内部使用共享的唯一一个ExecutorService
设置这个属性就可以一直传到ConsumerWorkService中。

除了ConnectionFactory.setShareExecutorService方法以外,
还可以在Connection被创建时,设置executorService
ConnectionFactory的newConnection方法:

public Connection newConnection(ExecutorService executor) throws IOException, TimeoutException;

总结

通过设置shareExecutorService,无论多少个channel,都可以统一控制线程数量、队列数量,
根据实际情况进行配置。

public class RabbitMqUtil {
    public static Channel getChannel() throws Exception{
        //创建一个连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        //连接服务器
        factory.setHost("114.***.***.***");
        //用户名
        factory.setUsername("admin");
        //密码
        factory.setPassword("123");

        //创建连接
//        ExecutorService executor = Executors.newFixedThreadPool(1);  设置线程池中的个数,把executor传给newConnection()
        Connection connection = factory.newConnection();
        //获取信道
        Channel channel = connection.createChannel();
        return channel;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的RabbitMQ线程消费端处理的示例代码: ```python import pika import threading class ConsumerThread(threading.Thread): def __init__(self, thread_id, queue_name): threading.Thread.__init__(self) self.thread_id = thread_id self.queue_name = queue_name def run(self): connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) channel = connection.channel() channel.queue_declare(queue=self.queue_name) def callback(ch, method, properties, body): print("Thread %d received %r" % (self.thread_id, body)) # do some processing here channel.basic_consume(queue=self.queue_name, on_message_callback=callback, auto_ack=True) channel.start_consuming() # create 5 consumer threads threads = [] for i in range(5): thread = ConsumerThread(i, 'my_queue') threads.append(thread) # start all threads for thread in threads: thread.start() # wait for all threads to finish for thread in threads: thread.join() ``` 该代码创建了一个名为`ConsumerThread`的类,该类继承自Python的`threading.Thread`类。每个线程都需要一个线程ID和队列名称作为参数。`run()`方法是每个线程运行的主体,其中连接到RabbitMQ并从队列中接收消息。每个线程都有自己的回调函数`callback()`,用于处理每个接收到的消息。 主程序创建了5个`ConsumerThread`实例,并启动所有线程。然后,主程序等待所有线程完成。当RabbitMQ队列中的消息到达时,它们将被随机分配给一个线程进行处理。每个线程都是独立的,可以同时处理多个消息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值