2

グルービー: 1.8.6

GPars: 0.12 または 1.2.1

OS: Ubuntu 14.04 LTS

@Grab(group='org.codehaus.gpars', module='gpars', version='0.12')
import groovyx.gpars.actor.Actor


import groovyx.gpars.actor.Actors


def a = 1
def b = 100000

def reactor2 = Actors.reactor {
    println " $it"
}

def reactor1 = Actors.reactor {
    println "$it"
    reactor2 << it
}

Actor actor = Actors.actor {
    (a..b).each {reactor1 << it}
}

actor.join()

reactor1.stop()
reactor1.join()

reactor2.stop()
reactor2.join()

このコードを実行すると、NullPointerException が頻繁に発生します。a と b の範囲が広いほど、このエラーが発生しやすくなります。ただし、範囲が制限されている場合、エラーは発生しません。

なぜエラーが発生したのか理解できません。

4

1 に答える 1

0

あなたが提供したコード例から、あなたが達成しようとしていることは 100% わかりません。Actor提供された範囲内の各値を試行し、提供された値を出力してメッセージに反応しようとしているようです。

それを考えると、あなたのコードにはいくつかの問題があります。主な問題は、loop{}クロージャーがないことです。これにより、Actorメッセージを処理した後、次の受信メッセージを確実に待機できます。

第二に、呼び出しstop()も役に立ちません。Actorが追加のメッセージを受信しないようにするだけです。すぐに join を呼び出すので、あなたの場合は何も害はありませんが、混乱を招きます。

これを機能させるために、コードを単純化して実際の例にします。

import groovyx.gpars.actor.Actors

def a = 1
def b = 100000

def actor = Actors.actor {
    loop {
       react {
            println it
        }
    }
}

(a..b).each {
    actor << it
}
actor.join()

この例では、範囲内の各値に対してメッセージがアクターに追加されます。アクターは値を出力することでメッセージに反応し、「ループ」クロージャーのために次の受信メッセージを待ちます。

したがって、その例はあなたが望むものを達成するはずです。ただし、コードで何が起こっているかを明確にするために、ここに説明があります。

がメッセージに「反応」するときActor、メッセージは に送信されますReactor。値を明示的に返さなくても、Groovy では Closure 内の最後の行が return ステートメントです。その結果、クロージャー内の最後の行は であるためprintln、その戻り値は null です。そのため、Reactornull が返されます。これは へのメッセージとして扱われ、Actor再度処理されます。

このシナリオを回避するには、返信メッセージを評価し、メッセージのみを委任するか、まだ処理されていない場合はメッセージを出力する必要があります。コードを更新しました。明確にするために、戻りメッセージとして意図的に「完了」を返します。nullメッセージを処理する前にチェックするようにコードを変更できます。

groovyx.gpars.actor.Actors のインポート

def a = 1
def b = 100000

def reactor2 = Actors.reactor { message ->
    if(!message.equals("done")) {
        println "\t\tReact Again: $message"
    }
    return "done"
}

def reactor = Actors.reactor { message ->
    if(!message.equals("done")) {
        println "\tReact: $message"
        reactor2 << message
    }
    return "done"
}

def actor = Actors.actor {
    loop {
        react {
            if(!it.equals("done")) {
                println it
                reactor << it
            }
        }
    }
}

(a..b).each {
    actor << it
    // actor.oi
}
actor.join()
于 2016-05-07T19:20:39.763 に答える