11

所以我设置了一个服务来从用户上传的文件中导入大量数据。我希望用户能够在处理文件时继续在网站上工作。我通过创建一个线程来实现这一点。

Thread.start {
 //work done here
}

现在问题出现了,我不想让多个线程同时运行。这是我尝试过的:

class SomeService {

Thread thread = new Thread()

 def serviceMethod() {
   if (!thread?.isAlive()) {
     thread.start {
        //Do work here
     }
   }
 }

}  

但是,这不起作用。thread.isAlive()总是返回假。关于我如何做到这一点的任何想法?

4

2 回答 2

17

我会考虑改用一个Executor

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()
 }

}

使用 anewSingleThreadExecutor将确保任务一个接一个地执行。如果有一个后台任务已经在运行,那么下一个任务将排队并在正在运行的任务完成时启动(serviceMethod本身仍将立即返回)。

如果您的“在这里工作”涉及 GORM 数据库访问,您可能希望考虑执行器插件,因为该插件将为您的后台任务设置适当的持久性上下文(例如 Hibernate 会话)。

于 2013-05-30T20:28:05.150 回答
2

另一种方法是使用 Spring 的@Async注解。

将以下内容添加到resources.groovy

beans = {
    xmlns task:"http://www.springframework.org/schema/task"
    task.'annotation-driven'('proxy-target-class':true, 'mode':'proxy')
}

您现在注释的任何服务方法都@Async将异步运行,例如

@Async
def reallyLongRunningProcess() {
    //do some stuff that takes ages
}

如果您只希望一个线程一次运行导入,您可以执行以下操作 -

class MyService {
    boolean longProcessRunning = false

    @Async
    def reallyLongRunningProcess() {
        if (longProcessRunning) return

        try {
            longProcessRunning = true
            //do some stuff that takes ages
        } finally {
            longProcessRunning = false
        }
    }
}
于 2013-05-30T22:53:03.637 回答