今天使用线程池来进行数据库操作是出现了空指针的错误,debug过程中发现Service类并没有因为@Autowired注解而自动注入
原因分析大概是:线程池新开的线程中不能使用 @Autowired 注入对象从而导致 NullPointerException被抛出
首先来看看原先的代码:
线程池:
public static final ThreadPoolExecutor poolExecutor =
new ThreadPoolExecutor(3, 6, 2,
TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(3));
进行数据库操作的线程:
@Component
@Scope("prototype")//spring 多例
public class DBThread implements Runnable {
private Integer id;
private static ReentrantLock lock = new ReentrantLock(true);
@Autowired
GoodsService goodsService;
public DBThread(){
super();
}
public DBThread(int id) {
this.id = id;
}
@Override
public void run() {
//在数据库插入数据
lock.lock();
try{
System.out.println("当前线程为"+Thread.currentThread().getId());
goodsService.buy(id);
}catch (Exception e){
throw e;
}finally {
System.out.println("当前线程解锁"+Thread.currentThread().getId());
lock.unlock();
}
}
}
执行类:
@RequestMapping("/buy/{Id}")
public String buy(@PathVariable("Id")Integer id){
ThreadPoolManager.poolExecutor.execute(new DBThread(id));
return "redirect:/refreshgoods";
}
然后我们修改的思路便是将DBThread 类中的goodsService从自动注入变为我们主动的从Applicationcaontext中将其取出来使用
也就是修改为如下代码:
private static ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
private static GoodsService goodsService;
static {
goodsService = context.getBean(GoodsService.class);
}
完整的:
@Component
@Scope("prototype")//spring 多例
public class DBThread implements Runnable {
private Integer id;
private static ReentrantLock lock = new ReentrantLock(true);
private static ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/applicationContext.xml");
private static GoodsService goodsService;
static {
goodsService = context.getBean(GoodsService.class);
}
public DBThread(){
super();
}
public DBThread(int id) {
this.id = id;
}
@Override
public void run() {
//在数据库插入数据
lock.lock();
try{
System.out.println("当前线程为"+Thread.currentThread().getId());
goodsService.buy(id);
}catch (Exception e){
throw e;
}finally {
System.out.println("当前线程解锁"+Thread.currentThread().getId());
lock.unlock();
}
}
}