Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Groovy 如何使用GPAR知道抛出异常时所有线程都已完成?_Groovy_Gpars - Fatal编程技术网

Groovy 如何使用GPAR知道抛出异常时所有线程都已完成?

Groovy 如何使用GPAR知道抛出异常时所有线程都已完成?,groovy,gpars,Groovy,Gpars,在线程抛出异常的情况下,如何等待所有未抛出异常的线程都完成(这样用户在所有线程停止之前不会再次启动) 我以几种不同的方式使用GPAR,因此我需要针对每种方式使用一种策略(并行集合、异步闭包和fork/join)。异常不会被掩埋,它们通过承诺、getChildrenResults等得到了很好的处理,因此这不是一个问题(感谢Vaclav Pech的回答)。我只需要确保主线程等待任何仍在运行的完成或停止 例如,当使用并行集合时,有些线程继续运行,而有些线程在异常发生后从不启动。因此,要知道有多少人在那

在线程抛出异常的情况下,如何等待所有未抛出异常的线程都完成(这样用户在所有线程停止之前不会再次启动)

我以几种不同的方式使用GPAR,因此我需要针对每种方式使用一种策略(并行集合、异步闭包和fork/join)。异常不会被掩埋,它们通过承诺、getChildrenResults等得到了很好的处理,因此这不是一个问题(感谢Vaclav Pech的回答)。我只需要确保主线程等待任何仍在运行的完成或停止

例如,当使用并行集合时,有些线程继续运行,而有些线程在异常发生后从不启动。因此,要知道有多少人在那里等待,或者可能要抓住他们并不容易

我猜可能有一种方法可以使用线程池(本例中是GParsPool)。有什么建议吗


谢谢

我相信您将需要捕获异常,然后返回预期结果以外的内容(例如,如果您期望的是数字,则返回字符串或null),即


我相信您将需要捕获异常,然后返回预期结果以外的内容(例如,如果您期望的是数字,则返回字符串或null),即


我相信我已经找到了解决这个问题的方法,在经过彻底测试后,我在应用程序中实现了它,并且可以正常工作

withPool闭包作为第一个参数传入创建的池(jsr166y.ForkJoinPool)。我可以获取它并将其存储在一个变量(currentPool)中,稍后由主线程使用,如下所示:

    GParsPool.withPool { pool ->
        currentPool = pool
当抛出异常并返回到主线程进行处理时,我可以让它等待所有事情完成,如下所示:

    } catch (Exception exc) {
        if (currentPool) {
            while (!currentPool.isQuiescent()) {
                Thread.sleep(100)
                println 'waiting for threads to finish'
            }
        }

        println 'all done'
    }
isquisite()似乎是确保没有更多工作要做的安全方法

请注意,在测试期间,我还发现异常似乎并不像我最初认为的那样终止循环的执行。如果我有一个500人的列表,并且每个人都并行,那么不管第一个到第二个是否有错误,他们都会运行。因此,我必须在并行循环的异常处理程序中使用currentPool.shutdownNow()终止循环。另见:

以下是实际解决方案的完整简化表示:

void example() {
    jsr166y.ForkJoinPool currentPool

    AtomicInteger threadCounter = new AtomicInteger(0)
    AtomicInteger threadCounterEnd = new AtomicInteger(0)

    AtomicReference<Exception> realException = new AtomicReference<Exception>()

    try {
        GParsPool.withPool { pool ->
            currentPool = pool

            (1..500).eachParallel {
                try {
                    if (threadCounter.incrementAndGet() == 1) {
                        throw new RuntimeException('planet blew up!')
                    }

                    if (realException.get() != null) {
                        // We had an exception already in this eachParallel - quit early
                        return
                    }

                    // Do some long work
                    Integer counter=0
                    (1..1000000).each() {counter++}

                    // Flag if we went all the way through
                    threadCounterEnd.incrementAndGet()
                } catch (Exception exc) {
                    realException.compareAndSet(null, exc)

                    pool.shutdownNow()
                    throw realException
                }
            }
        }
    } catch (Exception exc) {
        // If we used pool.shutdownNow(), we need to look at the real exception.
        // This is needed because pool.shutdownNow() sometimes generates a CancellationException
        // which can cover up the real exception that caused us to do a shutdownNow().
        if (realException.get()) {
            exc = realException.get()
        }

        if (currentPool) {
            while (!currentPool.isQuiescent()) {
                Thread.sleep(100)
                println 'waiting for threads to finish'
            }
        }

        // Do further exception handling here...
        exc.printStackTrace()
    }
}
void示例(){
jsr166y.ForkJoinPool当前池
AtomicInteger线程计数器=新的AtomicInteger(0)
AtomicInteger threadCounterEnd=新的AtomicInteger(0)
AtomicReference realException=新的AtomicReference()
试一试{
GParsPool.withPool{pool->
当前池=池
(1..500)。每个平行{
试一试{
if(threadCounter.incrementAndGet()==1){
抛出新的RuntimeException('星球爆炸!')
}
if(realeexception.get()!=null){
//我们在这场平行赛中已经出现了一个例外——提前退出
返回
}
//做些长时间的工作
整数计数器=0
(1..1000000).each(){counter++}
//旗子,如果我们一路通过
threadCounterEnd.incrementAndGet()
}捕获(异常exc){
realException.compareAndSet(null,exc)
pool.shutdownNow()
抛出realException
}
}
}
}捕获(异常exc){
//如果我们使用pool.shutdownNow(),我们需要查看真正的异常。
//这是必需的,因为pool.shutdownNow()有时会生成CancellationException
//这可以掩盖导致我们执行Shutdownow()的真正异常。
if(realeexception.get()){
exc=realeexception.get()
}
如果(当前池){
而(!currentPool.isquisite()){
线程。睡眠(100)
println“等待线程完成”
}
}
//在此执行进一步的异常处理。。。
exc.printStackTrace()
}
}
回到我前面的例子,如果我在4核机器上第一次抛出异常,大约有5个线程排队。shutdownNow()会在大约20个线程通过后切断连接,因此在顶部附近进行“提前退出”检查有助于这20个左右的线程尽快退出


只是把它贴在这里,以防它帮助了其他人,作为我在这里得到的所有帮助的回报。谢谢

我相信我已经找到了解决这个问题的方法,经过彻底的测试后,我在应用程序中实现了它,它可以正常工作

withPool闭包作为第一个参数传入创建的池(jsr166y.ForkJoinPool)。我可以获取它并将其存储在一个变量(currentPool)中,稍后由主线程使用,如下所示:

    GParsPool.withPool { pool ->
        currentPool = pool
当抛出异常并返回到主线程进行处理时,我可以让它等待所有事情完成,如下所示:

    } catch (Exception exc) {
        if (currentPool) {
            while (!currentPool.isQuiescent()) {
                Thread.sleep(100)
                println 'waiting for threads to finish'
            }
        }

        println 'all done'
    }
isquisite()似乎是确保没有更多工作要做的安全方法

请注意,在测试期间,我还发现异常似乎并不像我最初认为的那样终止循环的执行。如果我有一个500人的列表,并且每个人都并行,那么不管第一个到第二个是否有错误,他们都会运行。因此,我必须在并行循环的异常处理程序中使用currentPool.shutdownNow()终止循环。另见:

以下是实际解决方案的完整简化表示:

void example() {
    jsr166y.ForkJoinPool currentPool

    AtomicInteger threadCounter = new AtomicInteger(0)
    AtomicInteger threadCounterEnd = new AtomicInteger(0)

    AtomicReference<Exception> realException = new AtomicReference<Exception>()

    try {
        GParsPool.withPool { pool ->
            currentPool = pool

            (1..500).eachParallel {
                try {
                    if (threadCounter.incrementAndGet() == 1) {
                        throw new RuntimeException('planet blew up!')
                    }

                    if (realException.get() != null) {
                        // We had an exception already in this eachParallel - quit early
                        return
                    }

                    // Do some long work
                    Integer counter=0
                    (1..1000000).each() {counter++}

                    // Flag if we went all the way through
                    threadCounterEnd.incrementAndGet()
                } catch (Exception exc) {
                    realException.compareAndSet(null, exc)

                    pool.shutdownNow()
                    throw realException
                }
            }
        }
    } catch (Exception exc) {
        // If we used pool.shutdownNow(), we need to look at the real exception.
        // This is needed because pool.shutdownNow() sometimes generates a CancellationException
        // which can cover up the real exception that caused us to do a shutdownNow().
        if (realException.get()) {
            exc = realException.get()
        }

        if (currentPool) {
            while (!currentPool.isQuiescent()) {
                Thread.sleep(100)
                println 'waiting for threads to finish'
            }
        }

        // Do further exception handling here...
        exc.printStackTrace()
    }
}
void示例(){
jsr166y.ForkJoinPool当前池
AtomicInteger线程计数器=新的AtomicInteger(0)
原子霉素