MQ监听器下多线程安全问题

背景

今天在写MQ队列监听器队列的时候,突然有一个疑问,局部变量会不会受到多线程的影响,所以为此做了一个实验。

实验

我在监听器中定义了两个变量,一个是类变量,一个是局部变量。然后设置监听器的并发线程为2个、一次抓取线程的消息个数为10个,具体代码如下所示:

public int countPublic = 0;

@Override
@RabbitHandler
@RabbitListener(queues = "amz_advertisement:big_info", containerFactory = "rabbitListenerContainerFactoryAmzAdvertisementBig")
public void process(Message msg, Channel channel) {
    int countPrivate = 0;
    try {
        countPrivate++;
        countPublic++;
        logger.error("countPrivate:{},countPublic:{}", countPrivate, countPublic);
    } catch (Exception e) {
        logger.error("bigInfo错误,错误信息为:{}", ExceptionUtil.formatException(e));
    }
}

然后循环发送100个消息,推送到指定队列中,具体代码如下所示:

@RequestMapping("/sendMQ/{message}")
public Object sendMQ(@PathVariable("message")  String message) throws InterruptedException {
    for (int i=0;i<100;i++){
        Thread.sleep(100);
        amqpTemplateDelay.convertAndSend("amz_advertisement:big_info", "我是测试amz_advertisement:info的测试数据");
    }
    return "发送成功";
}

结果如下所示:

RabbitListenerEndpointContainer#0-1 [BigInfoAdvertistingListener.java: 43] - countPrivate:1,countPublic:1

RabbitListenerEndpointContainer#0-1 [BigInfoAdvertistingListener.java: 43] - countPrivate:1,countPublic:3

RabbitListenerEndpointContainer#0-2 [BigInfoAdvertistingListener.java: 43] - countPrivate:1,countPublic:3

RabbitListenerEndpointContainer#0-2 [BigInfoAdvertistingListener.java: 43] - countPrivate:1,countPublic:4

从结果中,我们可以很明显的看到:局部变量一致都是1没有递增,但是类变量一直在递增。

这是因为Spring默认以单例模式创建对象,所以多线程模式下类变量就会存在线程安全问题。但是局部变量,在多线程模式下是线程安全的,各个线程之间的局部变量都是独享的。

总结

有时候我们写代码不注意,就会把局部变量写成类变量,这个时候如果是多线程模式,那将是灾难性的。所以我们平时写代码一定要严谨,不要变量位置随意放置。今天的初试多线程就到这边,下一讲博主将会深入的给大家介绍复杂多线程应用场景。

林老师带你学编程https://wolzq.com

想要更多干货、技术猛料的孩子,快点拿起手机扫码关注我,我在这里等你哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章