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 我们在多线程开发中,可能会出现这种情况.就是一个线程需要另外一个线程满足某某条件才 ...
随机推荐
- JAVA的设计模式之装饰设计模式
1.装饰设计模式 顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: 2.看这个图可能不容易理解,举两个 ...
- MySQL 显示表字段及注释等信息
SHOW TABLES from resource [FROM db_name] //列出数据库数据表 SHOW TABLE STATUS from resource [FROM db_name] ...
- phpcms 新建模块安装
1.安装配置---小问题: 估计就我这么傻 T-T ,改成自己的目录名. 2.模块的目录: 模块存放在modules文件夹里,打开这个文件夹,里面的一个文件夹代表一个模块. 3.建立模块以及其基本目 ...
- 20165228 学习基础和C语言基础调查
========== 做中学读后感 我依然认为兴趣与自觉性是推动一个人进步的两大因素,他们之间的区别是"兴趣"带来的影响更多是主动性的学习,而"自觉"则是略显被 ...
- CodeForces - 1101D:GCD Counting (树分治)
You are given a tree consisting of n vertices. A number is written on each vertex; the number on ver ...
- xdoj1321----简单搜索
1321: 营救公主 时间限制: 1 Sec 内存限制: 128 MB提交: 156 解决: 37[提交][状态][讨论版] 题目描述 DSKer今天又做梦了,他的睡眠质量一直很差.他梦见他化身骑 ...
- HDU2023:求平均成绩
Problem Description 假设一个班有n(n<=50)个学生,每人考m(m<=5)门课,求每个学生的平均成绩和每门课的平均成绩,并输出各科成绩均大于等于平均成绩的学生数量. ...
- C语言--第一周作业评分和总结(5班)
作业链接:https://egdu.cnblogs.com/campus/hljkj/CS2017-5/homework/963 一.评分要求 * 要求1 (5分):博客中给出安装软件的截图(得分点1 ...
- JavaSE笔记
this关键字 哪个对象调用方法,方法定义中的this即为该对象的引用! static关键字 使用static声名的成员变量为静态成员变量,在第一次使用的时候被初始化,static成员变量只有一份 使 ...
- 2018.4.23 git命令总结
git clone git pull git add xx git add . git add -A git branch 查看本地分支 git branch --all 查看所有分支 git bra ...