2010-10-28 137 views
3

确定这个问题可能不会说太多,但这里的交易: 我正在学习scala并决定用一种方法创建一个实用类“FuncThread”名称参数的函数(我猜它称那是因为它是一个功能,但没有一个参数列表),然后启动一个线程与可运行这反过来执行传递的函数,我写了这样一类如下:为什么这个scala by-name参数的行为很奇怪

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

如果我取消注释第二条注释行,则测试通过,但如果仍有注释,则测试失败,这是正确的行为吗?如何以及何时执行名称参数函数?

我知道Scala有演员库,但我想尝试这个,因为我一直想做到这一点在Java中

回答

7

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

+0

哇这就是它,一个竞赛条件,只是增加了一个睡眠(10),并修复它! – Harima555 2010-10-28 15:21:50

+6

不,你添加了一个睡眠(10),并且掩盖了错误,但没有修复它。 – 2010-10-28 15:31:56

+0

是的你是对的,我应该用等待/通知来代替,但只是想扔一个快速测试玩Scala =) – Harima555 2010-10-28 20:04:40

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()); 
+0

太好了!感谢指出它,我没有充分看待演员的包,但我越发现斯卡拉我越爱它=) – Harima555 2010-10-28 20:25:24

相关问题