【问题标题】:why does this scala by-name parameter behave weirdly为什么这个 scala 的名字参数表现得很奇怪
【发布时间】:2011-05-01 22:40:49
【问题描述】:

好的,这个问题可能不会说太多,但这是交易: 我正在学习 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)
}

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

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

【问题讨论】:

    标签: scala


    【解决方案1】:

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

    【讨论】:

    • 哇,就是这样,一个竞争条件,刚刚添加了一个 sleep(10) 并修复了它!
    • 不,您添加了 sleep(10) 并掩盖了错误,没有修复它。
    • 是的,你是对的,我应该使用等待/通知来代替,但只是想快速测试一下以使用 scala =)
    • @Harima555 事实上,如果没有内存屏障,例如 synchronize 所提供的,你永远无法保证一个线程所做的更改会被另一个线程看到。查找 Java 内存模型。
    【解决方案2】:

    还值得注意的是(从 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());
    

    【讨论】:

    • 太好了!谢谢指点,我还没有完整看演员的包,但是我越发现scala我就越爱它=)
    猜你喜欢
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    • 2020-05-30
    • 2021-10-11
    相关资源
    最近更新 更多