Skip to content

"mainThreadPrefix = null " Causing multiple background bean locks to be blocked #35409

@xulisha123

Description

@xulisha123

version: v6.2.9

In DefaultListableBeanFactory.java will set this.mainThreadPrefix = null;

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		//
		//  为了保证扫描的顺序和创建的顺序一直ArrayList单独存储名字  it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		List<CompletableFuture<?>> futures = new ArrayList<>();

		this.preInstantiationThread.set(PreInstantiation.MAIN);
		this.mainThreadPrefix = getThreadNamePrefix();
		try {
			for (String beanName : beanNames) {
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				if (!mbd.isAbstract() && mbd.isSingleton()) {
					CompletableFuture<?> future = preInstantiateSingleton(beanName, mbd);
					// 存在异步创建bean
					if (future != null) {
						futures.add(future);
					}
				}
			}
		}
		finally {
			this.mainThreadPrefix = null;
			this.preInstantiationThread.remove();
		}

		if (!futures.isEmpty()) {
			try {
				CompletableFuture.allOf(futures.toArray(new CompletableFuture<?>[0])).join();
			}
			catch (CompletionException ex) {
				ReflectionUtils.rethrowRuntimeException(ex.getCause());
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName, false);
			if (singletonInstance instanceof SmartInitializingSingleton smartSingleton) {
				StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				smartSingleton.afterSingletonsInstantiated();
				smartInitialize.end();
			}
		}
	}

Suppose I have multiple background beans:

@Component
public class BatchBeanDefinitionRegister implements BeanDefinitionRegistryPostProcessor{


	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		for (int i=0;i<10;i++){
			RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(AService.class);
			// spring6:
			rootBeanDefinition.setBackgroundInit(true);
			registry.registerBeanDefinition("AService"+i,rootBeanDefinition);
		}
	}

public class AService {

	public AService() throws InterruptedException {
		Thread.sleep(5000);
	}
}

It takes not 5 seconds, but may take 10, 15, or 20 seconds, indicating that it will block synchronous creation.

But if I comment // this.mainThreadPrefix = null; The time taken is 5 seconds, indicating asynchronous creation bean.

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions