NB This is not about terminating a worker thread. It's about the aftermath of a normal termination.
I'm calling execute
in the EDT, so this spawns a "worker thread".
I'm calling worker.get()
in a Callable
which I submit to an ExecutorService
, specifically a ThreadPoolExecutor
.
The task ends OK (i.e. worker.get()
returns with a result, and the Callable
also ends OK).
I call shutdown()
on the Executor Service
: method terminates normally.
The puzzle comes when I examine the threads after this. This is in the context of unit testing, and I basically want to kill off all the activity which has been started during the last test.
I'm listing all the threads, and in addition to the various ones which were present before the test started I see this:
# thread Thread[pool-2-thread-1,5,main], state WAITING, alive True, interrupted False, thread group main
# thread Thread[SwingWorker-pool-4-thread-1,5,main], state WAITING, alive True, interrupted False, thread group main
The trouble is, as the tests get run, the newly constructed "Application" object makes a new thread pool each time, and more and more SwingWorkers
get created... and none of these threads appears to transition to the Thread.State
"TERMINATED" (which presumably would mean they would then cease to be listed).
I then tried calling join
on the "SwingWorker-pool-4-thread" Thread
... but this causes my current thread to hang.
Can anyone explain what's going on here and how to transition these threads to "TERMINATED"?
later
Response to 2 helpful comments. 10 threads, right. My thinking is just that a test if it fails (or an exception occurs) this can leave things in a troublesome state: suppose, in a functional test, 3 SWs are involved, and all sorts of publish/process
stuff is going on, not to mention various Runnable
s in the EDT. Before moving to the next test I want everything to be shut, closed, ended, killed, returned to a pristine, virginal state!
To ensure all Runnable
s have ended we have Robot.waitForIdle
(). I've also thought up a strategy for ensuring the publish/process
thing has ended: SwingWorker, done() is executed before process() calls are finished... . But in fact the latter, useful as it is, presupposes that the testing code knows which SWs to call the method on... I'm looking for a blunderbus, which will just kill em stone dead.
The toString
for these Thread objects shows clearly which has been created since starting the latest test... but I don't know how to kill 'em off. Isn't it the case that "WAITING" means that, vampire-like, they might rise up again and do all sorts of bad things? And just leaving vast numbers of "waiting" Threads hanging around, potentially running into their hundreds, seems a bit... untidy!
even later
Ah yes, getting hold of the AppContext
object is vital because you need to "reset" this in order to prevent RejectedExecutionException
. See my answer for how to do in Jython.
I also note that in the SW API doc it says
Because SwingWorker implements Runnable, a SwingWorker can be submitted to an Executor for execution.
This presumably means that you don't have to use SW's default executor at all. Might be the way to go, but unless needed for another reason in the app code, it kind of violates the principle of not tailoring the app code for the convenience of the testing code...