Scala 尾递归 java.lang.StackOverflowError
Scala Tail Recursion java.lang.StackOverflowError
我正在迭代查询一个名为 txqueue 的 mysql table,它正在不断增长。
每个后续查询仅考虑在上一次迭代中执行查询后插入到 txqueue table 中的行。
为了实现这一点,每个连续的查询都从 table 中选择行,其中主键(我下面示例中的 seqno 字段)超过了上一个查询中观察到的最大 seqno。
以这种方式识别的任何新插入的行都将写入 csv 文件。
此过程的目的是无限期地运行。
下面的尾递归函数工作正常,但过了一会儿它 运行 变成了 java.lang.WhosebugError。每次迭代查询的结果包含两到三行,并且大约每秒返回一次结果。
关于如何避免 java.lang.WhosebugError 的任何想法?
这实际上是 can/should 通过流媒体实现的吗?
非常感谢您的任何建议。
这是可以使用一段时间的代码:
object TXQImport {
val driver = "com.mysql.jdbc.Driver"
val url = "jdbc:mysql://mysqlserveraddress/mysqldb"
val username = "username"
val password = "password"
var connection:Connection = null
def txImportLoop(startID : BigDecimal) : Unit = {
try {
Class.forName(driver)
connection = DriverManager.getConnection(url, username, password)
val statement = connection.createStatement()
val newMaxID = statement.executeQuery("SELECT max(seqno) as maxid from txqueue")
val maxid = new Iterator[BigDecimal] {
def hasNext = newMaxID.next()
def next() = newMaxID.getBigDecimal(1)
}.toStream.max
val selectStatement = statement.executeQuery("SELECT seqno,someotherfield " +
" from txqueue where seqno >= " + startID + " and seqno < " + maxid)
if(startID != maxid) {
val ts = System.currentTimeMillis
val file = new java.io.File("F:\txqueue " + ts + ".txt")
val bw = new BufferedWriter(new FileWriter(file))
// Iterate Over ResultSet
while (selectStatement.next()) {
bw.write(selectStatement.getString(1) + "," + selectStatement.getString(2))
bw.newLine()
}
bw.close()
}
connection.close()
txImportLoop(maxid)
}
catch {
case e => e.printStackTrace
}
}
def main(args: Array[String]) {
txImportLoop(0)
}
}
你的函数不是尾递归的(因为最后的 catch
)。
这就是为什么你最终会出现堆栈溢出的原因。
你应该总是用 @scala.annotation.tailrec
注释你打算尾递归的函数 - 如果尾递归是不可能的,它会编译失败,这样你就不会在 [=16 时对它感到惊讶=]时间。
我正在迭代查询一个名为 txqueue 的 mysql table,它正在不断增长。
每个后续查询仅考虑在上一次迭代中执行查询后插入到 txqueue table 中的行。
为了实现这一点,每个连续的查询都从 table 中选择行,其中主键(我下面示例中的 seqno 字段)超过了上一个查询中观察到的最大 seqno。
以这种方式识别的任何新插入的行都将写入 csv 文件。
此过程的目的是无限期地运行。
下面的尾递归函数工作正常,但过了一会儿它 运行 变成了 java.lang.WhosebugError。每次迭代查询的结果包含两到三行,并且大约每秒返回一次结果。
关于如何避免 java.lang.WhosebugError 的任何想法?
这实际上是 can/should 通过流媒体实现的吗?
非常感谢您的任何建议。
这是可以使用一段时间的代码:
object TXQImport {
val driver = "com.mysql.jdbc.Driver"
val url = "jdbc:mysql://mysqlserveraddress/mysqldb"
val username = "username"
val password = "password"
var connection:Connection = null
def txImportLoop(startID : BigDecimal) : Unit = {
try {
Class.forName(driver)
connection = DriverManager.getConnection(url, username, password)
val statement = connection.createStatement()
val newMaxID = statement.executeQuery("SELECT max(seqno) as maxid from txqueue")
val maxid = new Iterator[BigDecimal] {
def hasNext = newMaxID.next()
def next() = newMaxID.getBigDecimal(1)
}.toStream.max
val selectStatement = statement.executeQuery("SELECT seqno,someotherfield " +
" from txqueue where seqno >= " + startID + " and seqno < " + maxid)
if(startID != maxid) {
val ts = System.currentTimeMillis
val file = new java.io.File("F:\txqueue " + ts + ".txt")
val bw = new BufferedWriter(new FileWriter(file))
// Iterate Over ResultSet
while (selectStatement.next()) {
bw.write(selectStatement.getString(1) + "," + selectStatement.getString(2))
bw.newLine()
}
bw.close()
}
connection.close()
txImportLoop(maxid)
}
catch {
case e => e.printStackTrace
}
}
def main(args: Array[String]) {
txImportLoop(0)
}
}
你的函数不是尾递归的(因为最后的 catch
)。
这就是为什么你最终会出现堆栈溢出的原因。
你应该总是用 @scala.annotation.tailrec
注释你打算尾递归的函数 - 如果尾递归是不可能的,它会编译失败,这样你就不会在 [=16 时对它感到惊讶=]时间。