在开发中经常会使用spring的@Autowired或@Resource来实现对象的自动注入,但是在最近的开发中在多线程中用Spring来自动注入时总是注入不进去,对象显示为null。
后来了解到 spring bean 出于线程安全考虑,不得注入bean至线程类(Runnable),如果线程中想使用spring实例,有两种方法:
1、将ThreadTest类也作为一个bean注入到spring容器中:
public class SpringMultiThreadTest{
@Autowired
private ThreadTest threadTest; //将线程类作为对象注入
@Test
public void testSpringBean(){
for (int i=0; i<10000000; i++){
new Thread(threadTest).start();
}
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
2、使用Spring手动获得ServiceBean:
(1)先写一个手动获得Spring bean的工具类
public class SpringBeanUtil implements ApplicationContextAware{
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringBeanUtil.applicationContext = applicationContext;
}
public static Object getBeanByName(String beanName) {
if (applicationContext == null){
return null;
}
return applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> type) {
return applicationContext.getBean(type);
}
}
(2)ThreadTest类中不自动获取,而是手动获取
public class ThreadTest implements Runnable{
private ServiceBean serviceBean;
private static AtomicInteger count = new AtomicInteger(0);
public ThreadRunner(){
this.serviceBean = (ServiceBean)SpringBeanUtil.getBeanByName("serviceBean");
}
@Override
public void run(){
if (serviceBean ==null){
return;
}
serviceBean.log();
count.addAndGet(1);
System.out.println("当前线程为:" + Thread.currentThread().getName() + "count:" + count);
}
public ServiceBean getServiceBean() {
return serviceBean;
}
public void setServiceBean(ServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}