springboot下多线程开发注意事项
基于springboot的多线程程序开发过程中,由于本身也需要注入spring容器进行管理,才能发挥springboot的优势。所以这篇文字主要用来记录开发中两者结合时需要注意的一些事项。
第一步我们把线程类的实例注入sping容器进行管理
@Configuration
@SpringBootApplication
@Import({ThreadConfig.class})
public class ThreadApp implements CommandLineRunner
{
public static void main(String[] args) throws Exception { ApplicationContext app = SpringApplication.run(ThreadApp .class, args);
//这里主要保存上下文对象实例,需要加上。SpringBootUtils类网上很多,可以自己搜下
SpringBootUtils.setApplicationContext(app); } //access command line arguments
@Override
public void run(String... args) throws Exception {
//do something
}
} //ComponentScan注解会扫描com.demo.thead下,也就是多线程类所在的包下的文件
@Configuration
@ComponentScan(basePackages = { "com.demo.thread"})
public class ThreadConfig{ }
这里使用springboot @Import 注解,把ThreadConfig里扫描到的包中带注解的示例,如@Component等注入到spring容器当中.
然后是线程的启动,这里在我的业务场景中有两种情况:
1、程序运行时,自动启动;
这在一般的可执行程序里面,当然可以直接在main函数里执行通过代码启动线程。但在springboot中,我们可以使用@PostConstruct注解的方式,让已经注入bean容器的线程对象自启动
@Component
public class demoThread extends Thread
{
//注意这里,如果你没有实现把多线程类的实例注入到spring容器中,这里你是无法拿到其他自动装配的对象实例的的,这也是我们第一步的意义所在。
@Autowired
private XxxService xxxService; @PostConstruct
public void start() {
super.start();
} public void run() {
// Ok,在这里你就可以实现线程要实现的功能逻辑了,自然也可以直接使用装配好的sevice对象实例。 }
}
2、在程序中,需要开启线程时启动,比如在从kafka接收数据,开启线程处理,当然这种情况下也需要通过第一步,把线程类实例注入到sping容器中
private TaskThread thread;
private ExecutorService taskPool= new ThreadPoolExecutor(
5, 10, 1000,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10),
new ThreadPoolExecutor.CallerRunsPolicy()); @KafkaListener(topics = "xxTopic")
public void receive(ConsumerRecord<Object, Object> consumerRecord) {
JSONObject json = JSON.parseObject(consumerRecord.value().toString());
//通过SpringBootUtils获取线程类的实例
thread = SpringBootUtils.getBean(TaskThread.class);
//启动线程
//new Thread(thread).start() ;
//向线程对象里传值
thread.init(i);
//放入线程池执行
taskPool.execute(thread); }
//注意这里是否添加@Scope("prototype")注解
@Component
@Scope("prototype")
public class TaskThread implements Runnable{
protected int value=0;
@Autowired
private XxxService xxxService;
//ThreadLocal 对象,单例模式下可以保证成员变量的线程安全和独立性。
public ThreadLocal<Integer> valueLocal = new ThreadLocal < Integer > () {
@Override
protected Integer initialValue() {
return 0;
}
};
protected static final Logger LOG = LoggerFactory.getLogger(GpsTaskThread.class);
@Override
public final void run() {
try {
LOG.info(value+"");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void init(int Value) {
this.value=Value;
}
}
在这里我们需要注意,TaskThread这个线程类在spirngboot中是否要添加@Scope("prototype")注解设置为多例模式还是默认单例模式。
在单例模式下SpringBootUtils.getBean(TaskThread.class) 每次返回的都是同一个对象,虽然不需要每次都创建新的对象,但无法保证成员变量的线程安全,也就是说在线程池中的执行的线程,它们的value值是共享的。而多例模式下,由于每次创建的都是一个新的线程对象,则不存在上述问题。
所以在这里请大家注意无论是我上面的示例代码还是平常的web开发中,spirngboot默认为单例模式,自定义的成员变量是线程不安全的,需要通过ThreadLocal 或这其他方法做同步处理。
回到我们当前的业务场景,在这里我们需要每个线程处理的value值不同,互不影响,那么通过@Scope("prototype")注解把TaskThread设置为多例模式。
总结
通过上面的示例,我们可以看到springboot与多线程的结合还是比较简单,通过配置,我们既可以在spring容器中管理线程类,也可以在线程中使用sping容器中的对象实例。同时我们在使用的过程当中要有意识的去注意线程安全方面的问题和内部运行机制的问题。当然这里理解的还是比较浅显,如果有不正确的地方还请大家指出与海涵。
关注微信公众号,查看更多技术文章。

springboot下多线程开发注意事项的更多相关文章
- Delphi多线程开发注意事项
Q1: 多线程中需避免多个线程同时向全局变量进行写入操作,导致访问冲突问题. A1: 可以通过使用加锁机制(比如:临界区.互斥.信号量)解决此问题. Q2:多线程中对于结构体和CLASS类型的全局变 ...
- Linux下c开发 之 线程通信(转)
Linux下c开发 之 线程通信(转) 1.Linux“线程” 进程与线程之间是有区别的,不过Linux内核只提供了轻量进程的支持,未实现线程模型.Linux是一种“多进程单线程”的操作系统.Linu ...
- Java进阶(三)多线程开发关键技术
原创文章,同步发自作者个人博客,转载请务必以超链接形式在文章开头处注明出处http://www.jasongj.com/java/multi_thread/. sleep和wait到底什么区别 其实这 ...
- Linux下c开发 之 线程通信
Linux下c开发 之 线程通信 1.Linux“线程” 进程与线程之间是有区别的,不过Linux内核只提供了轻量进程的支持,未实现线程模型.Linux是一种“多进程单线程”的操作系统.Linux本身 ...
- .NET基础拾遗(5)多线程开发基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- Java多线程开发系列之番外篇:事件派发线程---EventDispatchThread
事件派发线程是java Swing开发中重要的知识点,在安卓app开发中,也是非常重要的一点.今天我们在多线程开发中,穿插进来这个线程.分别从线程的来由.原理和使用方法三个方面来学习事件派发线程. 一 ...
- Java多线程开发系列之四:玩转多线程(线程的控制2)
在上节的线程控制(详情点击这里)中,我们讲解了线程的等待join().守护线程.本节我们将会把剩下的线程控制内容一并讲完,主要内容有线程的睡眠.让步.优先级.挂起和恢复.停止等. 废话不多说,我们直接 ...
- Java多线程开发系列之一:走进多线程
对编程语言的基础知识:分支.选择.循环.面向对象等基本概念理解后,我们需要对java高级编程有一定的学习,这里不可避免的要接触到多线程开发. 由于多线程开发整体的系统比较大,我会写一个系列的文章总结介 ...
- Java之多线程开发时多条件Condition接口的使用
转:http://blog.csdn.net/a352193394/article/details/39454157 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...
随机推荐
- 【Python】基础练习题-1
#练习1:从键盘输入两个数,并比较其大小,直到输入e/E退出程序 while 1: input_number=raw_inut("please input two numbers,enter ...
- math、numpy、pandas NaN 判断
>> np.nan == np.nan False >> np.nan is np.nan True >> math.nan is np.nan False > ...
- (转载)Peter Norvig:十年学会编程
作者 Peter Norvig 是计算机科学家,Google 的研究总监.在本文中,Peter Norvig会告诉你:为什么急功近利地学习软件开发技术是没效果滴? ================华丽 ...
- bootstrap 4 移除Glyphicons
/********************************************************************** * bootstrap 4 移除Glyphicons * ...
- 百练1678-整数的个数-2015正式A题
A:整数的个数 总时间限制: 1000ms 内存限制: 65536kB 描述 给定k(1< k < 100)个正整数,其中每个数都是大于等于1,小于等于10的数.写程序计算给定的k个正 ...
- N!的近似值_斯特林公式
公式: N! ~= sqrt(2 * PI * n) * ((n / e) ^n) 题目类型不慌都.
- pycharm中如何安装Scrapy库
先打开pycharm软件. 然后先安装pywin32和setuptools库. 安装成功后再尝试Twisted库,如果失败,就去晚上下载一个库:https://www.lfd.uci.edu/~goh ...
- hello1 web项目中web.xml作用分析
该web.xml文件包含Facelets应用程序所需的几个元素.使用NetBeans IDE创建应用程序时,将自动创建以下所有内容. 指定项目阶段的上下文参数: <context-param&g ...
- Light OJ 1199:Partitioning Game(SG函数模板)
Alice and Bob are playing a strange game. The rules of the game are: 1. Initially there are n p ...
- PTA——模拟除法
PTA 7-42 整除光棍 #include <stdio.h> int main() { ];//创建存表 ,count=; int n; ; scanf("%d", ...