2

(場合によっては)複数のスレッドから保護する必要があるアプリケーションがあります。そのためのテストを行うには、同時に複数のスレッドからメソッドを呼び出す必要があります。

class MyObject {

  val myMethodCalled = new AtomicBoolean()   

  def myMethod() = {

    if (myMethodCalled.getAndSet(true))
      throw new IllegalStateException("Do not call myMethod twice")
  }
}

上記のメソッドの例外をテストケースからトリガーしたいと思います。

これはで可能JVMですか?もしそうなら、それを行う方法は?

編集

仮想マシン内でまったく同時にメソッドを呼び出す方法があるかどうか(私が知らないトリックまたはクラスを使用して)疑問に思いました。それは不可能だと思います。

4

3 に答える 3

1

メソッドの途中でスリープするか()、時間のかかる忙しい作業を行うことでメソッドの処理を遅くしてから、Thread.sleep他の2つ以上のスレッドにできるだけ速くそのメソッドを呼び出させる必要があります。

また、1回限りの実行機能を抽象化して、単独でテストすることもできます。例えば

def onlyOnce[A](f: => A) = {
  if (myMethodCalled.getAndSet(true)) throw new Exception("Twice!")
  f
}

そして、これが実際に機能するかどうかをテストする必要がある場合は、fテストを簡単にするために実行速度を遅くします。それ以外の場合は、一度だけの方法で

def doSomething = onlyOnce {
}

これは、適切にテストした場合、問題が発生することはありません(の本体がの値を台無しにしないonlyOnceように、物事が適切にカプセル化されていると仮定します)。fmyMethodCalled

最後に、それ以外の場合の最善の策は、少なくとも3つの実際の実行スレッドを備えたマシンを使用し、そのうちの2つにビジーウェイトを実行させ、一方が他方が読み取っている揮発性変数を反転させてから、両方がメソッドを実行することです。これは本質的に信頼できるものではありませんが、2つの間に小さなビジーウェイトオフセットがあり、関連するスペースを何度もカバーしている場合は、少なくともほぼ常に大丈夫であるという統計的な議論を行うことができます。

于 2013-03-25T22:39:16.153 に答える
0

defをlazyvalに変更するだけで、1回だけ実行されることを保証できます。

object MyObject {

// static field
val myMethodCalled = new AtomicBoolean()   

// static method
lazy val myMethod = {
  if (myMethodCalled.getAndSet(true))
    throw new IllegalStateException("Do not call myMethod twice")
  }
}
于 2013-03-26T00:54:05.103 に答える
0

AtomicBooleanの必要性に少し戸惑っています。あなたはそれを使っているので、あなたはまともなことをしてテストを書くべきです。それは良い。ただし、スレッド化されたコードのテストは、JVMで非常に困難です(JVMのハンディキャップがなくても、他の言語では特に簡単ではありません)。

幸いなことに、あなたの場合にはもっと簡単な解決策があるかもしれません。特定のメソッドが誤って同時に使用されたことを検出しようとしているようです。代わりに、そのように使用されるのを防ぐことができますか?例えば:

class MyObject {
  def myMethod() {
    synchronized {
      .. stuff in here is serialized by the Hoare Monitor
    }
  }
}

効果的な代替戦略は、目的に合わせて設計されたモジュール内で順次動作を分離することです。これは、アクターパターンの背後にある一般的な原則であり、より一般的なCSP代数(Occam、Go、Limboで使用され、JCSP APIを介してJVMで利用可能)でもあります。シーケンシャルコードのテストは一般的にはるかに簡単なので、これらのパターンはタスクを管理可能なチャンクに分割するのに役立ちます。

並行性の失敗は4つありますが、テストだけでは完全に排除することはできません。これについては、少し前に記事を書きました

于 2013-03-26T21:06:16.413 に答える