为什么这个scala by-name参数表现得很奇怪

时间:2010-10-28 15:03:58

标签: scala

好的问题可能不多说,但这是交易: 我正在学习scala,并决定使用一个方法来创建一个实用程序类“FuncThread”,该方法接收一个名称参数函数(我想它的名字是因为它是一个函数但没有参数列表)然后启动一个带有可运行的线程反过来执行传递的函数,我写了如下类:

class FuncThread
{
   def runInThread( func: => Unit)
   {
     val thread = new Thread(new Runnable()
     {
        def run()
        {
          func
        }
     }

     thread.start()
   }
}

然后我写了一个如下的junit测试:

@Test
def weirdBehaivorTest()
{
  var executed = false
  val util = new FuncThread()
  util.runInThread
  {
    executed = true
  }

  //the next line makes the test pass....
  //val nonSense : () => Unit  = () => { Console println "???" }

  assertTrue(executed)
}

如果我取消注释第二个注释行,则测试通过,但如果它仍然被注释,则测试失败,这是正确的行为吗? by-name参数函数如何以及何时执行?

我知道Scala有actor库但我想尝试这个,因为我一直想用Java做这个

2 个答案:

答案 0 :(得分:7)

这只是竞争条件吗? runInThread启动线程,但是在另一个线程将其设置为true之前,您的断言测试'已执行'。添加额外的行意味着在测试之前执行更多的代码(以及时间),使“执行”更有可能被设置为真

答案 1 :(得分:4)

值得注意的是(从Scala 2.8开始),您尝试编写的构造在标准库中可用

import scala.actors.Futures._

future{
    executed = true
}

这个构造实际上比你描述的更强大,线程计算可以返回一个值,并且可以等待它。

import scala.actors.Futures._

//forks off expensive calculation
val expensiveToCalculateNumber:Future[Int] = future{
    bigExpensiveCalculation()  
}

// do a lot of other stuff

//print out the result of the expensive calculation if it's ready, otherwise wait until it is
println( expensiveToCalculateNumber());