You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何并行初始化150个EntityManagerFactory?

并行初始化多个EntityManagerFactory的解决方案

问题根源

你当前的代码看似用了线程池,但实际无法实现并行,核心问题有两个:

  1. 共享配置对象引发线程安全问题:直接修改persistenceUnitInfo.getProperties()返回的Properties实例,该实例可能被多个线程共享,导致配置修改时的竞争,最终阻塞初始化流程。
  2. 未等待任务完成就关闭线程池:try-with-resources会在代码块结束时立即关闭线程池,此时提交的初始化任务大概率还未执行完成,要么被中断,要么无法正常完成初始化。

修复后的并行初始化代码

import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
import javax.persistence.spi.PersistenceUnitInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public abstract class Test {
    private void initManagerFactories() {
        List<PersistenceUnitInfo> persistenceUnitInfos = getPersistenceUnitInfos();
        // 线程池大小不宜设置为150,避免耗尽系统资源,建议用CPU核心数的2倍作为上限
        int poolSize = Math.min(Runtime.getRuntime().availableProcessors() * 2, persistenceUnitInfos.size());
        
        try (ExecutorService executorService = Executors.newFixedThreadPool(poolSize)) {
            for(PersistenceUnitInfo persistenceUnitInfo : persistenceUnitInfos) {
                // 每个任务使用独立的Properties对象,避免多线程共享修改
                Properties properties = new Properties();
                properties.putAll(persistenceUnitInfo.getProperties());
                
                properties.setProperty("hibernate.current_session_context_class", "thread");
                properties.setProperty("hibernate.hql.bulk_id_strategy", "org.hibernate.hql.spi.id.inline.InlineIdsOrClauseBulkIdStrategy");
                properties.setProperty("hibernate.hbm2ddl.auto", "update");
                properties.setProperty("hibernate.hbm2ddl.jdbc_metadata_extraction_strategy", "individually");
                properties.setProperty("hibernate.order_inserts", "true");
                properties.setProperty("org.hibernate.envers.store_data_at_delete", "true");
                properties.setProperty("hibernate.search.backend.hosts", "localhost:9200");
                properties.setProperty("hibernate.search.backend.protocol", "http");
                properties.setProperty("hibernate.search.backend.schema_management.settings_file", "custom/index-settings.json");
                
                executorService.submit(() -> {
                    try {
                        // 执行EntityManagerFactory初始化
                        new EntityManagerFactoryBuilderImpl(
                            new PersistenceUnitInfoDescriptor(persistenceUnitInfo),
                            new HashMap<>()
                        ).build();
                    } catch (Exception e) {
                        // 捕获并处理初始化异常,避免静默失败
                        e.printStackTrace();
                    }
                });
            }
            
            // 先关闭线程池接收新任务,再等待所有已提交任务完成
            executorService.shutdown();
            try {
                // 设置超时时间,根据实际情况调整(比如150个实例,单个10秒,设置30分钟足够)
                if (!executorService.awaitTermination(30, TimeUnit.MINUTES)) {
                    // 超时后强制终止未完成的任务
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    public abstract List<PersistenceUnitInfo> getPersistenceUnitInfos();
}

核心优化说明

  • 独立配置实例:每个初始化任务复制一份Properties配置,避免多线程共享修改引发的竞争问题,确保并行初始化的线程安全。
  • 合理线程池大小:直接创建150个线程会耗尽内存、数据库连接等系统资源,用CPU核心数*2作为线程池上限,平衡并行效率和资源消耗。
  • 等待任务完成:调用shutdown()和awaitTermination(),确保所有EntityManagerFactory初始化完成后再关闭线程池,避免任务被中断。
  • 异常捕获:在任务内部捕获异常,避免单个实例初始化失败导致整个流程静默出错,方便排查问题。

额外注意事项

  • 数据库连接池配置:150个EntityManagerFactory会占用大量数据库连接,需确保数据库最大连接数足够,同时每个实例的连接池参数(如hibernate.c3p0.max_size)要合理配置,避免连接耗尽。
  • Hibernate Search资源控制:每个实例会初始化Elasticsearch客户端,并行创建可能给ES带来压力,可调整hibernate.search.backend.connections.max参数控制ES连接数。

内容的提问来源于stack exchange,提问作者user32575965

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 12:42:25