首页 > 解决方案 > 如何在groovy中从TimerTask返回值

问题描述

我试图每3 秒调用一次getStatus方法并检查我是否从我的数据库中获得了完成状态(为此测试目的删除数据库代码)。一旦我得到状态“完成”,我就会退出 while 循环,我想将此状态返回给 testMethod。但是我的代码没有将任何内容返回给 CompletableFuture。我在这里做错了什么 - 有人可以帮我解决这个问题吗?我的代码片段:

CompletableFuture.supplyAsync({ -> getStatus()
        }).thenAccept({ status -> testMethod(status) })

def getStatus() {
        def response
        Timer timer = new Timer()
        TimerTask timerTask = new TimerTask(){
                    @Override
                    public void run() {
                        while(true) {
                            // Doing some DB operation to check the work status is changing to Done and assigning to response
                            response = "Done"
                            if (response == "Done") {
                                timer.cancel()
                                break;
                            }

                        }
                    }
                }
        timer.schedule(timerTask, 3000)
        return response
    }


def testMethod(status) {
        System.out.println("testMethod... " +status)
    }

标签: asynchronousgroovytimertimertaskcompletable-future

解决方案


问题是您正在调度计时器任务,然后立即从 getStatus() 返回响应的当前值。大约 3 秒后,该任务将局部变量设置为“完成”,但任务之外的任何人现在都没有看到它。

更好的方法可能是让 getStatus 本身返回 CompletableFuture。任务完成后可以填充的内容。

所以是这样的:

getStatus().thenAccept({ status -> testMethod(status) })

def getStatus() {
   def future = new CompletableFuture<String>()
   Timer timer = new Timer()
   TimerTask timerTask = new TimerTask(){
      @Override
      public void run() {
         while(true) {
            // Doing some DB operation to check the work status is changing to Done and assigning to response
            def response = "Done"
            if (response == "Done") {
               timer.cancel()
               future.complete(response)
               break;
            }

         }
      }
   }
   timer.schedule(timerTask, 3000)
   return future
}


def testMethod(status) {
   System.out.println("testMethod... " +status)
}

编辑 - 要添加某种超时,您可以改为使用 ScheduledExecutorService,如下所示:

import java.util.concurrent.*


ScheduledExecutorService executor = Executors.newScheduledThreadPool(2)

getStatus(executor).thenAccept({ status -> testMethod(status) })


def getStatus(executor) {
   def future = new CompletableFuture<String>()

   def count = 0

   def task

   def exec = {
      println("Running : $count")
      // Doing some DB operation to check the work status is changing to Done and assigning to response
      def response = "NotDone"
      if (response == "Done") {
         future.complete(response)
         task.cancel()
      }
      else if (++count == 10) {
         future.complete("Failed")
         task.cancel()
      }
   } as Runnable

   task = executor.scheduleAtFixedRate(exec, 3, 3, TimeUnit.SECONDS)

   future
}


def testMethod(status) {
   System.out.println("testMethod... " +status)
}

所以我只是使用迭代计数来阻止它运行超过 10 次,但这可能是基于计数或时间的。任何对您的用例有意义的东西。


推荐阅读