[ https://issues.apache.org/jira/browse/UIMA-6412?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Richard Eckart de Castilho resolved UIMA-6412. ---------------------------------------------- Resolution: Fixed > Stop using ThreadGroup in CPMEngine > ----------------------------------- > > Key: UIMA-6412 > URL: https://issues.apache.org/jira/browse/UIMA-6412 > Project: UIMA > Issue Type: Improvement > Components: Collection Processing > Reporter: Richard Eckart de Castilho > Assignee: Richard Eckart de Castilho > Priority: Major > Fix For: 3.3.0SDK > > > The {{CPMEngine}} internally uses a {{ThreadGroup}} to manage the worker > threads. This causes a problem with concurrency features present in modern > Java versions, e.g. the static system-wide {{ForkJoinPool.commonPool()}} > which is used by concurrency features by default when no other pool is > specified. But even if a custom pool is used, the problem persists. The > problem is that threads launched from within the context of a thread that is > part of a thread group inherits that thread group as its parent. > Consequently, worker threads launched e.g. by the > {{ForkJoinPool.commonPool()}} become part of the CPM thread group. The common > pool worker threads are long-lived and re-used. the CPM thread group however > refuses to shut down as long as there are still threads in it. That > essentially blocks the use of many concurrency features within the scope of a > CPE. > The best approach would probably be to replace the {{CPMThreadGroup}} with > some kind of {{CPMExecutorService}} which essentially performs the same > duties as the thread group but without being a thread group. > * {{CPMThreadGroup.uncaughtException()}} - instead of handling the uncaught > exceptions at the level of the thread group, an exception handler needs to be > installed in the individual spawned threads > * {{ThreadGroupDestroyer}} - this is the code that currently waits until all > threads in the {{CPMThreadGroup}} are finished and then destroys the group to > avoid {{CPMThreadGroup}}-instances piling up over time. I guess the > replacement would be to call {{shutdown()}} on the replacement executor > service. {{shutdown()}} causes the executor service not to accept any new > tasks and once all running tasks are done, it cleans itself up. > * worker threads must not be started by callling {{start()}} explicitly but > rather by submitting them to the executor service > * The CPE allows configuring a custom output queue (instance of > {{BoundedWorkQueue}}. There is one subclass of {{BoundedWorkQueue}} provided > by UIMA which is the {{SequencedQueue}} and it internally spawns a new > {{ExpirationTimer}} thread. In the current implementation, this timer thread > would block the thread group from shutting down. However, the task of the > {{ExpirationTimer}} is just to remove a map entry after a certain amount of > time - it is not a long running thread. So I think that it doesn't matter > that it won't block the execution service from shutting down and also that we > do not have to change the API for registering custom output queues to pass > the execution service into the custom queues. There might be custom queues > which rely on the thread group being blocked, but I somewhat doubt it - and > if so, those will then have to change their implementation... I'd still call > this a feature release change and not a major release change. > * This removes the public {{CPMThreadGroup}} class and replaces it with a > {{CPMExecutorService}}. Again this is a change of an API that is in principle > public and such changes should only be done in major releases. But again, I > doubt that anybody really depends on this particular API. I think it is > mainly public because the class is used by another class in a different > package and otherwise it should be considered internal. So - IMHO - fine for > a feature-level release. -- This message was sent by Atlassian Jira (v8.20.1#820001)