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】进程3
#练习: import time from multiprocessing import Pool def run(fn): #fn: 函数参数是数据列表的一个元素 time.sleep(1) ret ...
- mssql,mysql,Oracle 数据库中获得UUID字符串
sql server : select replace(newId(),'-','') oracle :select sys_guid() from dual SQL> select sys_g ...
- Jquery的deferred对象,看这2篇牛人的文章,基本就够了。
http://blog.csdn.net/ligang2585116/article/details/51589073 http://www.ruanyifeng.com/blog/2011/08/a ...
- JSON JAVA 总结
1.如下是我所用json第三方jar包的maven坐标 <!--可引用的jar--> <dependency> <groupId>net.sf.json-lib&l ...
- 20155219 2016-2017-2 《Java程序设计》第7周学习总结
20155219 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 认识时间与日期 时间的度量 1.格林威治时间(GMT):通过观察太阳而得,因为地球公转轨道为 ...
- day022 python (re模块和 模块)
re模块是python提供的一套关于正则表达式的模块.核心功能有四个: 1.findall (查找所有,返回list) lst=re.findall("m",'salalwmaop ...
- java-Arrays类
1.Arrays类概述: - 针对数组进行操作的工具类. - 提供了排序,查找等功能. 2.成员方法: - 转换成字符串:public static String toString(int[] a) ...
- Python下载与安装配置
最近想学习Python那就开始吧 首先就是下载安装了 Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:https://www.python.org/ 你 ...
- Redis(二)持久化
Redis持久化,分为RDB方式和AOF方式,它们可以单独使用,也可以混用.Redis默认的是使用RDB方式. 一.RDB方式 1.触发快照的方式 RDB方式是在指定时间间隔内某一时间点的数据集快照. ...
- 使用python requests模块搭建http load压测环境
网上开源的压力测试工具超级的多,但是总有一些功能不是很符合自己预期的,于是自己动手搭建了一个简单的http load的压测环境 1.首先从最简单的http环境着手,当你在浏览器上输入了http://w ...