【问题标题】:Scala - While loop with an Iterator and also with a state checkerScala - 带有迭代器和状态检查器的 While 循环
【发布时间】:2018-03-28 12:51:23
【问题描述】:

首先,我是 Scala 新手。我有以下(工作)Scala 方法,必须等待长达 15 秒才能完成记录。通常,7 秒后,记录就完成了。所以,我放了一个最多 15 秒的迭代器,如果记录完成它就会停止(我不知道如何停止迭代,除了 drop 之外)。如果没有完成,它应该休眠 1 秒。问题是我必须将方法 checkIfRecordIsComplete 作为参数给出,因为我可能会将此等待方法与其他布尔函数一起使用。我怎样才能使用等待方法......让我们说checkIfOtherIsComplete?谢谢!

def checkIfRecordIsComplete(record: Record) = {
    println("record.state="+record.state)
    if(record.state.contains(Constants.RecordStatusComplete))
      true
    else
      false
}

def checkIfOtherIsComplete(other: Other) = {
    println("other.state="+other.state)
    if(other.state.contains(Constants.OtherStatusComplete))
      true
    else
      false
}

def wait(recordId: RecordId, maxW: Int): Unit = {
    val it = Iterator.iterate(1){_+1}.take(maxW)
    while(it.hasNext) {
      val recordList = getRecord(recordId)
      recordList.records.foreach {
        record => {
          if(!checkIfRecordIsComplete(record)){
            Thread.sleep(1000)
            it.next()
          }
          else
            it.drop(maxW)
        }
      }
    }
}

........................
wait(recordId, 15)

【问题讨论】:

    标签: scala while-loop iterator


    【解决方案1】:

    您需要找到一种为RecordOther 提供通用功能的类型。在这种情况下,这可能是两者都实现的trait。例如:

    trait Completable {
    
      def isComplete: Boolean
    
    }
    

    现在,RecordOther 都应该扩展它:

    trait Record extends Completable {
    
      // ...
    
      override def isComplete: Boolean = this.state.contains(Constants.RecordStatusComplete)
    
    }
    
    trait Other extends Completable {
    
      // ...
    
      override def isComplete: Boolean = this.state.contains(Constants.OtherStatusComplete)
    
    }
    

    wait 函数应稍作更改,以便访问Completables 的序列(列表)。事实上,既然检查逻辑现在在RecordOther内部,就不需要像checkIfOtherIsComplete这样的专用函数了:

    // returns the Completable to be checked for completion.
    // replaces the former getRecord
    private def getItems(recordId: RecordId): Seq[Completable] = ???
    
    def wait(recordId: RecordId, maxW: Int): Unit = {
      val it = Iterator.iterate(1){_+1}.take(maxW)
      while(it.hasNext) {
        getItems(recordId).foreach{
          item => if (item.isComplete) {
            Thread.sleep(1000)
            it.next()
          } else {
            it.drop(maxW)
          }
        }
      }
    }
    

    顺便说一句,我有点怀疑使用这种Iterator 方法进行此类检查的实施解决方案的可靠性。但是由于它有效,因此您的情况可能没问题。如果您有兴趣,我们可以继续讨论。

    更新

    实现等待序列的另一种方法可能是使用scala.concurrent.* 包中的标准Scala 功能。

    我们可以使用Future 并等待其完成。例如:

    import scala.concurrent.duration.Duration
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent.{Await, Future}
    
    def wait2(recordId: RecordId, maxW: Int): Unit = {
      val waitForAllComplete = Future {
        while(!getItems(recordId).forall(_.isComplete)) {
          Thread.sleep(1000)
        }
      }
      Await.ready(waitForAllComplete, Duration(maxW, "second"))
    }
    

    现在,如果序列在maxW 秒后未完成,则会抛出TimeoutException。如果您需要确保列表中的所有项目都处于预期状态并处理意外情况,这可能会有所帮助。

    更新结束

    【讨论】:

    • 除了这个迭代器解决方案之外,您能建议我其他解决方案吗?谢谢!!!
    猜你喜欢
    • 2015-06-25
    • 2015-02-08
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2014-05-08
    • 2015-01-25
    • 2011-06-20
    相关资源
    最近更新 更多