ConcurrentException / NullPointerException в GParsPool runForkJoin - PullRequest
1 голос
/ 18 февраля 2011

Для небольшого контекста я пытаюсь решить проблему Project Euler 31 , используя превосходную поддержку GParsPool Fork / Join .

Для этого я написал следующий код:

import groovyx.gpars.*
import groovy.util.GroovyCollections

@Grab(group="org.codehaus.gpars", module="gpars", version="0.11")
def getMatchingCombos(target) {
    combos = [200, 100 /*, 50, 20, 10, 5, 2, 1*/]
    GParsPool.withPool(1) { pool ->
        combos = combos.collectParallel { n ->  
            ((0..(target/n)).step(1) as TreeSet).collect { p -> p*n }
        }
        return GParsPool.runForkJoin(combos, 0, 0, target) { usableCombos, comboIndex, sum, targetSum ->
            def offset = "\t"*comboIndex
            def results = 0
            if(sum<=targetSum) {
                if(comboIndex<combos.size()) {
                    usableCombos[comboIndex].each { n ->
                        println offset+"now trying with $comboIndex element value $n (curent sum is $sum)"
                        results += forkOffChild(usableCombos, comboIndex+1, sum+n, targetSum)
                    }
                } else {
                    if(sum==targetSum) {
                        results +=1
                        println offset+"sum is target ! so we have $results"
                    }
                }
            }
            return results;
        }
    }
}

println getMatchingCombos(200)

К сожалению, каждый раз, когда я пытаюсь запустить это, я получаю следующую трассировку стека:

now trying with 0 element value 0 (curent sum is 0). Known combos are [[0, 200], [0, 100, 200]] and target is 200
        now trying with 1 element value 0 (curent sum is 0). Known combos are [[0, 200], [0, 100, 200]] and target is 20
0
Caught: java.util.concurrent.ExecutionException: java.lang.NullPointerException
        at groovyx.gpars.GParsPool.runForkJoin(GParsPool.groovy:305)
        at probleme_31$_getMatchingCombos_closure1.doCall(probleme_31.groovy:18)
        at groovyx.gpars.GParsPool$_withExistingPool_closure1.doCall(GParsPool.groovy:170)
        at groovyx.gpars.GParsPool$_withExistingPool_closure1.doCall(GParsPool.groovy)
        at groovyx.gpars.GParsPool.withExistingPool(GParsPool.groovy:169)
        at groovyx.gpars.GParsPool.withPool(GParsPool.groovy:141)
        at groovyx.gpars.GParsPool.withPool(GParsPool.groovy:117)
        at probleme_31.getMatchingCombos(probleme_31.groovy:9)
        at probleme_31.run(probleme_31.groovy:41)

Я понимаю, что это как-то связано с тем, как я хочу использовать Fork / Join в качестве рекурсивного "сплющивающего" механизма, но что за ошибка я здесь делаю?

1 Ответ

3 голосов
/ 18 февраля 2011

Вы неправильно пытаетесь прочитать дочерние результаты как возвращаемое значение из метода forkOffChild (), в то время как это должно быть сделано с помощью getChildrenResults ().

        return GParsPool.runForkJoin(combos, 0, 0, target) { usableCombos, comboIndex, sum, targetSum ->
        def offset = "\t"*comboIndex
        def results = 0
        if(sum<=targetSum) {
            if(comboIndex<combos.size()) {
                usableCombos[comboIndex].each { n ->
                    println offset+"now trying with $comboIndex element value $n (curent sum is $sum)"
                    forkOffChild(usableCombos, comboIndex+1, sum+n, targetSum)
                }
            } else {
                if(sum==targetSum) {
                    results +=1
                    println offset+"sum is target ! so we have $results"
                }
            }
        }
        results += getChildrenResults().sum(0)
        return results;
    }
...