使用多线程时,普通类调用service层方法报空指针异常
1.多线程配置
/**
* 配置线程池参数 根据自己需要配置
*/
private static ExecutorService cachedThreadPool = new ThreadPoolExecutor(0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
namedThreadFactory);
2.线程调用方法
/**
* 线程池调用方法
*
* @param param
*/
public void run(BatchStartFlowParam param) {
cachedThreadPool.execute(new SendMsg(param));
}
3.发送消息类
/**
* 发送消息类
*
* @param param
*/
public class SendMsg implements Runnable {
private BatchStartFlowParam param;
public SendMsg(BatchStartFlowParam param) {
this.param = param;
}
@Autowired
private StartFlowService startFlowService;
@Override
public void run() {
log.info(Thread.currentThread().getName());
startFlowService.startFlowList(param);
}
}
如下图:startFlowService 报空指针异常,并没有通过 @Autowired 注入进来。
4.问题描述及解决方法
单独开的线程中不能使用 @Autowired 注入对象从而导致 java.lang.NullPointerException,而是应该从 Spring 容器中获取该对象进行引用。
代码修改如下,只需修改第三步的发送消息类如下
public class SendMsg implements Runnable {
private BatchStartFlowParam param;
public SendMsg(BatchStartFlowParam param) {
this.param = param;
}
private static StartFlowService startFlowService;
static {
//从 Spring 容器中 获取 startFlowService 对象
startFlowService = SpringContext.getBean(StartFlowService.class);
}
@Override
public void run() {
log.info(Thread.currentThread().getName());
startFlowService.startFlowList(param);
}
}
解决方案2
还有一种解决方案如下:
将上述的线程调用方法修改如下,只需修改上面第二步的线程调用方法,新增一个发送消息方法 sendMsg();并修改线程调用发送消息的方法,如下所示。
@Autowired
private StartFlowService startFlowService;
/**
* 线程池调用方法
*
* @param param
*/
public void run(BatchStartFlowParam param) {
//cachedThreadPool.execute(new SendMsg(param));
cachedThreadPool.execute(() -> {
sendMsg(param);
});
}
/**
* 发送消息
*
* @param param
*/
public void sendMsg(BatchStartFlowParam param) {
System.out.println(Thread.currentThread().getName());
System.out.println(JSONObject.toJSONString(param));
startFlowService.startFlowList(param);
}