Groovy 完成所有工作后终止现有池

Groovy 完成所有工作后终止现有池,groovy,gpars,Groovy,Gpars,好的,GPAR是全新的,所以如果这有一个明显的答案,请原谅我 这是我的设想。我们目前有一段代码包装在Thread.start{}块中。它这样做是为了在后台将消息发送到消息队列,而不是阻止用户请求。我们最近遇到的一个问题是,对于大的工作块,用户可能会执行另一个操作,从而导致此块再次执行。由于是线程化的,第二批消息可能在第一批消息之前发送,从而导致数据损坏 我想将此过程更改为使用GPAR的队列流。我见过创建池的示例,例如 def pool = GParsPool.createPool() 或 然后

好的,GPAR是全新的,所以如果这有一个明显的答案,请原谅我

这是我的设想。我们目前有一段代码包装在Thread.start{}块中。它这样做是为了在后台将消息发送到消息队列,而不是阻止用户请求。我们最近遇到的一个问题是,对于大的工作块,用户可能会执行另一个操作,从而导致此块再次执行。由于是线程化的,第二批消息可能在第一批消息之前发送,从而导致数据损坏

我想将此过程更改为使用GPAR的队列流。我见过创建池的示例,例如

def pool = GParsPool.createPool()

然后将池用作

GParsPool.withExistingPool(pool) {
    ...
}
这似乎可以解释这样一种情况:如果用户再次执行操作,我可以重用创建的池,并且如果池大小为1,操作不会无序执行

我的问题是,这是使用GPAR实现这一点的最佳方法吗?此外,我如何知道游泳池何时完成所有工作?当所有的工作都完成时,它会终止吗?如果是,是否有一种方法可用于检查池是否已完成/终止,以知道我需要一个新池


任何帮助都将不胜感激。

不,显式创建的池不会自行终止。您必须显式地对它们调用shutdown()


但是,使用withPool(){}命令将保证一旦代码块完成,池就会被销毁。

这是我们目前解决问题的方法。应该注意的是,由于我们的要求,我们遵循了这条路线

  • 工作是按上下文分组的
  • 给定上下文中的工作是有序的
  • 给定上下文中的工作是同步的
  • 上下文的其他工作应在前面的工作之后执行
  • 工作不应阻止用户请求
  • 上下文之间是异步的
  • 一旦上下文的工作完成,上下文本身就应该清理干净
鉴于上述情况,我们实施了以下措施:

class AsyncService {
    def queueContexts


    def AsyncService() {
        queueContexts = new QueueContexts()
    }

    def queue(contextString, closure) {
        queueContexts.retrieveContextWithWork(contextString, true).send(closure)
    }

    class QueueContexts {
        def contextMap = [:]

        def synchronized retrieveContextWithWork(contextString, incrementWork) {
            def context = contextMap[contextString]

            if (context) {
                if (!context.hasWork(incrementWork)) {
                    contextMap.remove(contextString)
                    context.terminate()
                }
            } else {
                def queueContexts = this
                contextMap[contextString] = new QueueContext({->
                    queueContexts.retrieveContextWithWork(contextString, false)
                })
            }

            contextMap[contextString]
        }

        class QueueContext {
            def workCount
            def actor

            def QueueContext(finishClosure) {
                workCount = 1
                actor = Actors.actor {
                    loop {
                        react { closure ->
                            try {
                                closure()
                            } catch (Throwable th) {
                                log.error("Uncaught exception in async queue context", th)
                            }

                            finishClosure()
                        }
                    }
                }
            }

            def send(closure) {
                actor.send(closure)
            }

            def terminate(){
                actor.terminate()
            }

            def hasWork(incrementWork) {
                workCount += (incrementWork ? 1 : -1)
                workCount > 0
            }
        }
    }
}

我很困惑。withPool和withExistingPool块执行似乎都是如此。在池完成后执行闭包之后,我做了一些spock测试和逻辑。这不是我想要的。我不希望池阻止执行。那么您可能需要不同的抽象。一般来说,数据流任务和承诺给了您更多的灵活性。我相信我们有一个使用参与者的有效解决方案。一旦我们确定满意,我将发布最终解决方案:)
class AsyncService {
    def queueContexts


    def AsyncService() {
        queueContexts = new QueueContexts()
    }

    def queue(contextString, closure) {
        queueContexts.retrieveContextWithWork(contextString, true).send(closure)
    }

    class QueueContexts {
        def contextMap = [:]

        def synchronized retrieveContextWithWork(contextString, incrementWork) {
            def context = contextMap[contextString]

            if (context) {
                if (!context.hasWork(incrementWork)) {
                    contextMap.remove(contextString)
                    context.terminate()
                }
            } else {
                def queueContexts = this
                contextMap[contextString] = new QueueContext({->
                    queueContexts.retrieveContextWithWork(contextString, false)
                })
            }

            contextMap[contextString]
        }

        class QueueContext {
            def workCount
            def actor

            def QueueContext(finishClosure) {
                workCount = 1
                actor = Actors.actor {
                    loop {
                        react { closure ->
                            try {
                                closure()
                            } catch (Throwable th) {
                                log.error("Uncaught exception in async queue context", th)
                            }

                            finishClosure()
                        }
                    }
                }
            }

            def send(closure) {
                actor.send(closure)
            }

            def terminate(){
                actor.terminate()
            }

            def hasWork(incrementWork) {
                workCount += (incrementWork ? 1 : -1)
                workCount > 0
            }
        }
    }
}