springboot开发之多线程理解单例研究线程池学习和项目运行问题解决

Posted openglnewbee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot开发之多线程理解单例研究线程池学习和项目运行问题解决相关的知识,希望对你有一定的参考价值。

springboot多线程问题和单例相关研究

一直以来对springboot中的多线程和并发的实际应用没有进行一个深入的了解,今天对相关的知识进行了学习和验证(基于springboot 2.x)。总结如下:

  1. controller、service、repository 默认都是单例形式存在,若需要多例可以通过手动加上@Scope(“prototype”)的方式来实现;
  2. controller的访问由tomcat触发,实际测试发现tomcat内部应该存在线程池的调度机制,不同的请求很可能来自不同的线程(也可能相同);
  3. 单例形式的对象通过autowired引入,不会重复创建,会复用对象;
  4. service的调用一般由controller触发,因此也可能来自不同的线程;
  5. 基于以上几点原因,代码的编写需要考虑多线程安全的问题;
  6. static关键字的变量是类变量;final关键字的变量一旦创建赋值后不能更改;

想比较简单的解决并发问题,需要controller和 service都设置成多例(理想化,实际生产一般不应该如此做,还是需要通过多线程编程相关的实现和保护来解决并发问题)。

4.并发问题,关于并发问题,基于该场景先明确下什么情况下会发生并发问题呢。一般若每个线程中的静态变量、实例(对象)变量只有读操作、而无写操作,那么通常情况下这个全局变量是线程安全的;但是若有多个线程同时执行写操作,那么通常情况下需要考虑线程同步问题,否则就可能会出现线程安全问题。如:
1)常量始终是线程安全的,因为只存在读操作;
2)局部变量(包括方法的参数变量和方法内变量)是线程安全的。因为每执行一个方法,都会在独立的空间(栈帧)创建局部变量,它不是共享的资源;
3)成员变量(实例变量和类变量)会受到多线程影响。对于成员变量的操作,可以使用ThreadLocal来保证线程安全(threadlocal很容易理解,就是针对不同线程创建不同的对象,因此不需要考虑同步;若实际应用场景需要多线程共享变量,那么threadlocal就不适合,threadlocal变量可以在单个线程中共享使用);

4)类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而对象变量则属对象私有,某一个对象将其值改变,不影响其他对象。

最后说明下关于变量的基本概念,在java语言里,根据定义变量位置的不同,可以将变量分成两大类:

成员变量,存在与堆内存中和类一起创建。如实例变量(不以static修饰)、类变量(以static修饰);
局部变量,存在与栈内存中,当方法执行完成后,让出内存让其它方法来使用内存。如形参(方法签名中定义的变量)、方法局部变量(在方法内部定义的变量)、代码块局部变量(在代码块内定义的变量)

参考文档:
https://blog.csdn.net/shiluyong8068/article/details/113833644?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link ()(单例,多线程)
https://blog.csdn.net/xiongxianze/article/details/70832899 (threadlocal使用)
https://blog.csdn.net/weixin_45041678/article/details/103894767 (注解,单例,多例)

线程池

说起多线程,在java开发中一般被更广泛使用的是线程池。通过@Async(“asyncServiceExecutor”) 这样的注解 (其中 asyncServiceExecutor 是线程池全局配置类中的方法名),可以很方便的把一个java方法异步化,通过线程池去执行。对应到我们的业务场景,比如一些响应返回不需要的操作(如更新数据库、发送kafka消息等)可以使用线程池简单的异步化,不影响controller的返回。

参考:
https://blog.csdn.net/weixin_42128988/article/details/112732710
这篇文章对线程池的使用进行了说明,并附有demo,我在本机基于demo进行了简单的修改并运行,验证结果符合预期。

github项目运行

1.项目代码下载完成后,通过idea打开
2.实测是否翻墙不是很影响,需要等待几分钟的时间,不会很久,idea导入完成
3.需要执行mvn install
4.需要检查代码类是否被正常识别,若没有正常识别,说明mvn库的配置有问题。进入右侧maven边栏,打开扳手,maven home directory 选择内置的bundled (maven 3) , apply
5.configuration配置启动类,spring boot, 选择应用启动类,并将配置命名为类名。
6.正常运行项目测试即可。

TODO:

maven相关的知识是比较基础的,类似cocoapods,有空可以多研究研究,对于工程和打包方面的问题解决有帮助。

以上是关于springboot开发之多线程理解单例研究线程池学习和项目运行问题解决的主要内容,如果未能解决你的问题,请参考以下文章

springboot开发之多线程理解单例研究线程池学习和项目运行问题解决

springboot开发之多线程理解单例研究线程池学习和项目运行问题解决

springboot开发之多线程理解单例研究线程池学习和项目运行问题解决

springboot开发之多线程理解单例研究线程池学习和项目运行问题解决

SpringBoot开发案例之多任务并行+线程池处理

设计模式 - 单例模式之多线程调试与破坏单例