Managing threads in Grails Services
I would consider using an Executor
instead.
import java.util.concurrent.*import javax.annotation.*class SomeService {ExecutorService executor = Executors.newSingleThreadExecutor() def serviceMethod() { executor.execute { //Do work here } } @PreDestroy void shutdown() { executor.shutdownNow() }}
Using a newSingleThreadExecutor
will ensure that tasks execute one after the other. If there's a background task already running then the next task will be queued up and will start when the running task has finished (serviceMethod
itself will still return immediately).
You may wish to consider the executor plugin if your "do work here" involves GORM database access, as that plugin will set up the appropriate persistence context (e.g. Hibernate session) for your background tasks.
Another way to do this is to use Spring's @Async
annotation.
Add the following to resources.groovy
:
beans = { xmlns task:"http://www.springframework.org/schema/task" task.'annotation-driven'('proxy-target-class':true, 'mode':'proxy')}
Any service method you now annotate with @Async
will run asynchronously, e.g.
@Asyncdef reallyLongRunningProcess() { //do some stuff that takes ages}
If you only want one thread to run the import at a time, you could do something like this -
class MyService { boolean longProcessRunning = false @Async def reallyLongRunningProcess() { if (longProcessRunning) return try { longProcessRunning = true //do some stuff that takes ages } finally { longProcessRunning = false } }}