Scala流如何使用16个线程?

时间:2019-06-10 17:21:59

标签: scala parallel-processing stream lazy-evaluation

我一直在尝试使用流在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

0 个答案:

没有答案