`

多线程中使用Spring的注入问题

阅读更多

 

在开发中经常会使用Spring的@Autowired来实现对象的自动注入,但是在最近的开发中在多线程中用Spring的@Autowired来自动注入时总是注入不进去,代码如下:

package com.common.base.utils.SpringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.atomic.AtomicInteger;

public class ThreadRunner implements Runnable{

    @Autowired
    private ServiceBean serviceBean;

    private static AtomicInteger count = new AtomicInteger(0);

    @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;
    }
}

 其中,ServiceBean定义如下:

package com.common.base.utils.SpringUtils;

import org.springframework.stereotype.Service;

@Service("serviceBean")
public class ServiceBean{

    public void log(){
        System.out.println("this is service bean.");
    }
}

 只是简单的输出语句。然后在主线程中,启动线程,如下:

package com.common.base.utils.SpringUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:Service-*.xml"})
public class SpringMultiThreadTest{
    @Test
    public void testSpringBean(){
        for (int i=0; i<10000000; i++){
            new Thread(new ThreadRunner()).start();
        }

        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

 此时,不会有打印信息,serviceBean为空。

原因:在主线程中使用了:

new ThreadRunner()

 新建了一个实例,并不在Spring容器中,也就没法获得Spring中的bean。

解决办法:

1、将ThreadRunner类也作为一个bean注入到spring容器中,如下:

 

package com.common.base.utils.SpringUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:Service-*.xml"})
public class SpringMultiThreadTest{
    @Autowired
    private ThreadRunner threadRunner;
    @Test
    public void testSpringBean(){
        for (int i=0; i<10000000; i++){
            new Thread(threadRunner).start();
        }
        try {
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

 问题解决。

2、使用Spring手动获得ServiceBean,首先写一个手动获得Spring bean的工具类:

package com.common.base.utils.SpringUtils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 直接通过Spring 上下文获取SpringBean,用于多线程环境
 * by jingquan @20160405
 */

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);
	}

}

 然后在ThreadRunner类中不自动获取,而是手动获取,代码如下:

package com.common.base.utils.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadRunner 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;
    }
}

 问题解决。

 

分享到:
评论
1 楼 dawntop 2017-12-11  
Spirng4 有@EnableAsync和Async注解,完全可以实现比new thread简单很多的多线程。

相关推荐

    线程中获取spring 注解bean

    理解并熟练掌握这些方法,有助于在多线程环境下高效、安全地使用Spring注入的bean。在实际开发中,应根据具体需求选择合适的方式,确保代码的可读性、可维护性和性能。在进行线程处理时,还要注意线程安全问题,避免...

    Spring 多线程下注入bean问题详解

    在 Spring 框架中,多线程下注入 Bean 是一个常见的问题。本文将详细介绍 Spring 多线程下注入 Bean 问题,并提供两种解决方案。 问题描述 在多线程环境下,使用 Spring 框架时,可能会遇到 Bean 注入失败的问题。...

    java中spring里实现多线程

    当我们谈到在Spring中实现多线程,实际上是在讨论如何在Spring环境中创建、管理和协调并发执行的任务。这涉及到Java的并发API以及Spring对这些API的包装和扩展。 首先,让我们了解Java中的多线程基础。在Java中,...

    多线程Autowire注入null的解决方案.docx

    当我们在多线程中使用 @Autowired 注解时,可能会出现 null 的情况。这是因为多线程是防注入的,容器中的组件不会自动注入到多线程中。 解决方案一:将需要使用的service当做多线程实现类的一个属性参数 在多线程...

    maven管理的Spring多线程任务demo

    为了在Spring中使用`ThreadPoolTaskExecutor`,我们需要在配置类中声明一个bean,如下所示: ```java @Configuration public class ThreadPoolConfig { @Bean(name = "threadPoolTaskExecutor") public ...

    spring4+junit4.8 +多线程TheadTool

    3. **多线程(TheadTool)**:在Java中,我们可以使用`java.lang.Thread`类来创建和管理线程,但实际开发中可能会遇到一些复杂情况,如线程同步、线程池管理等。TheadTool可能是自定义的工具类,用于简化多线程编程...

    多线程及spring相关面试专题及答案.zip

    在IT行业中,多线程和Spring框架是两个非常重要的领域,尤其对于后端开发者来说,它们是必备的技术栈。下面将分别对这两个主题进行详细的知识点解析。 **多线程** 1. **线程概念**:线程是操作系统分配CPU时间片的...

    HttpClient+ Spring实现多线程

    标题 "HttpClient + Spring 实现多线程" 涉及到的是如何在Spring框架中使用Apache HttpClient库来创建一个支持多线程的HTTP客户端服务。Apache HttpClient是一个强大的HTTP客户端API,它提供了丰富的功能来处理HTTP...

    spring-boot-multithreading.zip_spring boot_多线程

    在Spring Boot应用中,多线程的使用是一个关键特性,特别是在处理高并发或者需要执行耗时操作时。本文将深入探讨Spring Boot如何实现多线程,并结合提供的`spring-boot-multithreading.zip`压缩包中的示例进行讲解。...

    详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决

    SpringBoot 多线程处理任务中无法@Autowired注入bean问题解决 在 SpringBoot 应用程序中,多线程处理任务是一个常见的场景,但是,在多线程处理任务中无法使用 @Autowired 注入 bean,这是一个常见的问题。今天,...

    java 后端学习资料包含(spring,多线程).zip

    总之,"java 后端学习资料包含(spring,多线程)"这个资料包是Java开发者深入学习和提升的宝贵资源,无论是对于Spring框架的使用还是多线程技术的掌握,都将带来实质性的进步。通过学习和实践,开发者可以更好地应对...

    解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题

    在本文中,我们主要探讨了在使用Spring Session以及Redis作为存储方式时,由于消息监听导致创建大量线程的问题及其解决方案。我们将从Spring Session的基础知识、Redis在Spring Session中的作用、监听机制导致线程...

    Springboot实现多线程注入bean的工具类操作

    总之,Spring Boot通过`ApplicationContextAware`接口和相关的工具类,使得在多线程环境中获取和使用bean变得简单易行,避免了手动管理bean实例的问题,保证了代码的整洁和可维护性。同时,这种方式也确保了bean的...

    解决SpringBoot项目使用多线程处理任务时无法通过@Autowired注入bean问题

    "解决SpringBoot项目使用多线程...使用TaskExecutor机制可以解决该问题,通过在配置文件中添加TaskExecutor的配置,并在Controller层中使用@Autowired注解来注入TaskExecutor,然后使用TaskExecutor来执行我们的任务。

    java简单分布式架构,多个数据源,线程池多线程访问

    综上所述,这个项目涉及到的知识点包括:分布式系统设计、Java多线程与线程池、Spring框架的多数据源支持、MyBatis的使用以及Spring的事务管理。通过这些技术的组合,可以构建出一个高效、可扩展的分布式应用,以...

    spring boot中多线程开发的注意事项总结

    在Spring Boot中,多线程开发是提升应用性能和并发能力的重要手段。Spring Boot通过`TaskExecutor`接口提供了一种方便的方式来实现多线程和...理解并遵循这些注意事项将有助于构建健壮、高效的多线程Spring Boot应用。

    使用spring框架整合DBUtils技术,实现用户转账功能

    在本例中,我们可以创建一个`UserService`接口,用于处理转账操作,然后使用Spring来注入实现该接口的类。这样,我们可以在不修改代码的情况下更换或扩展服务的实现。 接下来,我们谈谈DBUtils。DBUtils是Apache的...

    20万字必备java面试八股文宝典-多线程.数据库.Spring.SpringBoot.Linux.分布式.设计模式.面试指导

    这份宝典囊括了Java编程中的基础知识、多线程编程、数据库操作、Spring框架、Spring Boot、Spring Cloud、Linux操作系统、分布式系统、设计模式、面试指导以及自我介绍等内容。 基础部分,包括Java编程语言的核心...

    基于Spring+Ibatis的安全线程实现

    在多线程环境中,线程安全是个关键问题。当多个线程并发访问共享资源时,如果没有正确的同步机制,可能会导致数据不一致、死锁等问题。在Spring框架中,我们可以通过以下几种方式实现线程安全: 1. **ThreadLocal**...

    Quartz注入Spring的Bean

    3. **Spring注入Bean到Job**:在Job执行时,我们可以直接注入其他由Spring管理的Bean,无需在Job中创建这些对象,从而减少了代码的复杂性,增强了可重用性。 4. **JobFactory的自定义**:Quartz默认使用...

Global site tag (gtag.js) - Google Analytics