猿问

使用阻塞队列的对象池在死锁中运行

我有一个在 payara 5 中运行的 Java 应用程序。


我需要汇集一些我的 bean 将使用的引擎对象(来自库)。创建引擎需要在单独的线程中完成。


因此我想出了我的 EnginePool 和我的 EngineProducer。这个想法是 EnginePool 管理两个 BlockingQueues。一个用于可用引擎,另一个用于被 bean 使用并需要再次变为可用的引擎。EnginePool 应该只可用一次,所以它是一个单例。


@Singleton

@Startup

@LocalBean

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)

public class AbbyyEnginePool implements OcrEnginePool<IEngine> {

private static final Logger logger = LoggerFactory.getLogger(AbbyyEnginePool.class);


@Resource(lookup = "java:comp/DefaultManagedThreadFactory")

private ManagedThreadFactory threadFactory;


private static final int DEFAULT_ENGINE_COUNT = 3;

private BlockingQueue<EngineMetaInfo> availableEngines = new ArrayBlockingQueue<>(DEFAULT_ENGINE_COUNT);

private BlockingQueue<IEngine> enginesToRelease = new ArrayBlockingQueue<>(DEFAULT_ENGINE_COUNT);

private Map<IEngine, IEngine> proxiesMapping = new ConcurrentHashMap<>(DEFAULT_ENGINE_COUNT);

private int poolSize;


public AbbyyEnginePool() {

    this(DEFAULT_ENGINE_COUNT);

}


public AbbyyEnginePool(int poolSize) {

    this.poolSize = poolSize;

    availableEngines = new ArrayBlockingQueue<>(poolSize);

    enginesToRelease = new ArrayBlockingQueue<>(poolSize);

    proxiesMapping = new ConcurrentHashMap<>(poolSize);

}


void setThreadFactory(ManagedThreadFactory threadFactory) {

    this.threadFactory = threadFactory;

}


@PostConstruct

void init() {

    EngineProducer engineProducer = new EngineProducer(availableEngines, enginesToRelease, poolSize);       

    Thread engineProducerThread = threadFactory.newThread(engineProducer);


    engineProducerThread.setName("engineProducer");

    engineProducerThread.start();


}


largeQ
浏览 196回答 1
1回答

一只甜甜圈

问题是容器管理所有并发。在单例的情况下,这意味着对字段的所有访问都将获得写锁。解决方案是使用@ConcurrencyManagement(BEAN) 注解。这意味着 bean 控制并发管理并且必须确保完成同步。
随时随地看视频慕课网APP

相关分类

Java
我要回答