如何从多个线程同时调用方法?

时间:2013-03-25 22:21:40

标签: java scala jvm

我有一个应用程序应该(在某些情况下)防止多个线程。为了进行测试,我需要同时从多个线程调用一个方法。

class MyObject {

  val myMethodCalled = new AtomicBoolean()   

  def myMethod() = {

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

我想从测试用例中触发上述方法中的异常。

这可能在JVM吗?如果是的话,该怎么做?

修改

我想知道是否有任何方法(使用某些技巧或我不知道的类)在虚拟机中同时调用方法。我猜这是不可能的。

3 个答案:

答案 0 :(得分:1)

你应该通过在它的中间睡眠(Thread.sleep)或做一些耗时的繁忙工作来减慢方法的处理速度,然后让两个或更多其他线程尽可能快地调用该方法。

您还可以抽象出仅运行一次的功能,以便您可以单独测试它。 E.g。

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

然后当你需要测试这实际上是否有效时,你传入一个缓慢执行的f来简化测试。否则,用你曾经的方法

def doSomething = onlyOnce {
}

如果您已正确测试onlyOnce,则不会出错(假设事情被正确封装,以便f的主体不会弄乱myMethodCalled的值。)< / p>

最后,你最好的选择是使用一台至少有三个实际执行线程的机器,并且其中两个执行繁忙等待,其中一个翻转另一个正在读取的volatile var,然后运行该方法。这本身并不可靠,但是如果你在两者之间有很小的忙等待偏移并且多次覆盖相关空间,你至少可以做一个统计论证,你至少几乎一直都没事。

答案 1 :(得分:0)

只需将你的def改为懒惰,你可以保证它只运行一次:

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")
  }
}

答案 2 :(得分:0)

我对AtomicBoolean的需求感到有些困惑。因为你正在使用它,你应该做正确的事情并编写测试。非常好。但是,在JVM上测试线程代码非常困难(即使没有JVM的障碍,在其他语言中也不是特别容易)。

幸运的是,在您的情况下可能会有一个更简单的解决方案。看起来您可能正在尝试检测特定方法何时被意外同时使用。您是否可以阻止使用它?例如:

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

有效的替代策略是在专门设计的模块中隔离顺序行为。这是actor模式背后的一般原则,也是更通用的CSP代数(在Occam,Go,Limbo中使用,并通过JCSP API在JVM上可用)。测试顺序代码通常要容易得多,因此这些模式可以帮助您将任务划分为可管理的块。

有四个并发失败,仅靠单独测试无法消除,关于I wrote an article a while ago