初试多线程

image

背景

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

实验

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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个消息,推送到指定队列中,具体代码如下所示:

1
2
3
4
5
6
7
8
@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

林老师带你学编程 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!