我的用例是创建一个Bean“B”列表,每个都有一个从属bean“C”的不同实例。
@Component("a")
public class A{
List<B> bPool = new ArrayList<>();
private ApplicationContext appContext;
@Autowired
A(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
for(int i=0; i<POOL_SIZE; i++){
bPool.add((B) appContext.getBean("b"));
}
}
//code for multi-threading, which uses beans from the list bPool.
//I iterate the list, launch multiple threads,
//pass different data to each thread and combine results.
List<CompletableFuture> multiThreads = new ArrayList<>();
Iterator it = bPool.iterator();
for(Data d : listOfSomeData){ //same size for listOfSomeData and bPool
CompletableFuture var = CompletableFuture.supplyAsync(() -> {
B curr = (B) it.next()
curr.someMethodInB(d);
});
multiThreads.add(var);
}
multiThreads.forEach(cf -> cf.join());
}
@Component("b")
@Scope("prototype")
public class B{
//Service class - has some dependencies, like C below
private C c;
private ApplicationContext appContext;
@Autowired
B(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
c = (C) appContext.getBean("c");
}
}
@Component("c")
@Scope("prototype")
public class C{
//this class holds some data and does some processing on it,
//I want this to be different for different instances in different threads.
}
在bPool中创建B列表时,在构建时(我在后构造中通过打印检查),分别为每个B设置了不同的C实例。
但是,稍后在同一个池中使用B实例时,所有B实例都具有相同的C实例。
它们都有C实例,它被设置为bPool的最后一个创建的B元素。
我是springboot的新手,无法理解这种行为。任何帮助赞赏。感谢
答案 0 :(得分:0)
仍然不确定导致问题的原因。然而,一种不同的方法解决了我的用例。
我继续使用spring本身提供的Async功能。
在主类中,添加@EnableAsync注释并创建要运行的后台线程池。
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args).close();
}
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("ThreadName-");
executor.initialize();
return executor;
}
}
使用带有@Async注释的公共方法创建一个新类,其中包含我们想要在后台运行的重代码。此方法需要是公共的,并且必须在不同的类中才能进行代理工作。我们无法在调用它的同一个类中创建这个异步方法。
@Component
public class MyAsyncService {
@Async
public CompletableFuture<ResultClass> myAsyncMethod(String params){
//do some heavy tasks here
return CompletableFuture.completedFuture(instanceOfResultClass);
}
}
使用来自调用者类的异步方法调用上述类。
@Component
public class CallerService{
private MyAsyncService myAsyncService;
@Autowired
public CallerService(MyAsyncService myAsyncService){
this.myAsyncService = myAsyncService;
}
public void myMethod(){
CompletableFuture<ResultClass> result1 = myService.findUser("PivotalSoftware");
CompletableFuture<ResultClass> result2 = gitHubLookupService.findUser("CloudFoundry");
CompletableFuture.allOf(result1, result2).join();
ResultClass finalResult1 = result1.get();
ResultClass finalResult2 = result2.get();
}
}