我一直在尝试使用流在Scala中生成素数,并且看起来流在并行运行。
起初,我遇到了尺寸限制,然后才能真正运行很长时间,但是现在,我将其更改为SafeLong并摆脱了任何阻碍因素,它一直在为该产品生成高达100,000,000的质数过去10到20分钟(非常慢,是的,但这不是重点)。
问题是,现在它可以运行一段时间,我注意到我的CPU使用率约为70%。奇怪,所以我检查了任务管理器,发现70%几乎全部是Java平台,并且均匀地分布在所有16个线程中。
代码如下:
import java.io.{File, PrintWriter}
import spire.math.SafeLong
import spire.implicits._
object PrimesTester {
def main(args: Array[String]): Unit = {
val max: SafeLong = 100000000
println("Grabbing stream...")
def primes: Stream[SafeLong] = getPrimesLazy(max)
println("Done.")
println("Opening file...")
val oFile = new PrintWriter(new File(s"lazyPrimes_$max.txt"))
println("Done.")
println("Generating and saving...")
for(p <- primes){
oFile.println(p)
}
oFile.close()
println("Done.")
}
def getPrimesLazy(max: SafeLong): Stream[SafeLong] = {
//Generate all relevant odd numbers
def odds: Stream[SafeLong] = Stream.iterate(3: SafeLong)(_ + 2).takeWhile(n => n*n <= max)
//Generate all composite numbers in the range
def composites: Stream[SafeLong] = odds.flatMap{ n =>
Stream.iterate(n * n)(_ + 2 * n).takeWhile(_ <= max)
}
//Take all composite numbers out of the range
2 #:: Stream.iterate(3: SafeLong)(_ + 2).takeWhile(_ <= max).diff(composites)
}
}
我很确定流是顺序的,而且我从未见过并行集合的行为是这样的。
这让我感到非常好奇,因为按照我对流的理解,这种情况不会发生。但是我们到了。有人知道发生了什么吗?
编辑:这是运行约一个小时后的线程转储:
"main@1" prio=5 tid=0x1 nid=NA runnable
java.lang.Thread.State: RUNNABLE
at spire.math.SafeLong$.apply(SafeLong.scala:211)
at spire.math.SafeLongIsCRing.fromInt(SafeLong.scala:526)
at spire.math.SafeLongIsCRing.fromInt$(SafeLong.scala:526)
at spire.math.SafeLongInstances$SafeLongAlgebra$.fromInt(SafeLong.scala:509)
at spire.math.SafeLongInstances$SafeLongAlgebra$.fromInt(SafeLong.scala:509)
at spire.syntax.LiteralIntMultiplicativeSemigroupOps$.$times$extension(Ops.scala:189)
at misc.PrimesTester$.$anonfun$getPrimesLazy$4(PrimesTester.scala:34)
at misc.PrimesTester$$$Lambda$14.1902260856.apply(Unknown Source:-1)
at scala.collection.immutable.Stream$.$anonfun$iterate$1(Stream.scala:1207)
at scala.collection.immutable.Stream$$$Lambda$19.2082351774.apply(Unknown Source:-1)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1171)
- locked <0x52d> (a scala.collection.immutable.Stream$Cons)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1161)
at scala.collection.immutable.Stream.$anonfun$takeWhile$1(Stream.scala:880)
at scala.collection.immutable.Stream$$Lambda$10.641853239.apply(Unknown Source:-1)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1171)
- locked <0x52e> (a scala.collection.immutable.Stream$Cons)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1161)
at scala.collection.immutable.Stream.$anonfun$append$1(Stream.scala:255)
at scala.collection.immutable.Stream$$Lambda$20.262366552.apply(Unknown Source:-1)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1171)
- locked <0x52f> (a scala.collection.immutable.Stream$Cons)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1161)
at scala.collection.immutable.Stream.foreach(Stream.scala:534)
at scala.collection.SeqLike.occCounts(SeqLike.scala:500)
at scala.collection.SeqLike.diff(SeqLike.scala:455)
at scala.collection.SeqLike.diff$(SeqLike.scala:454)
at scala.collection.AbstractSeq.diff(Seq.scala:45)
at misc.PrimesTester$.$anonfun$getPrimesLazy$6(PrimesTester.scala:38)
at misc.PrimesTester$$$Lambda$5.1885996206.apply(Unknown Source:-1)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1171)
- locked <0x52a> (a scala.collection.immutable.Stream$Cons)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1161)
at scala.collection.immutable.Stream.foreach(Stream.scala:534)
at misc.PrimesTester$.main(PrimesTester.scala:21)
at misc.PrimesTester.main(PrimesTester.scala:-1)
"Finalizer@1318" daemon prio=8 tid=0x3 nid=NA waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler@1319" daemon prio=10 tid=0x2 nid=NA waiting
java.lang.Thread.State: WAITING
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:502)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
"Attach Listener@1316" daemon prio=5 tid=0x5 nid=NA runnable
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher@1317" daemon prio=9 tid=0x4 nid=NA runnable
java.lang.Thread.State: RUNNABLE