Как этот поток Scala использует 16 потоков? - PullRequest
2 голосов
/ 10 июня 2019

Я экспериментировал с использованием потоков для генерации простых чисел в Scala, и почему-то похоже, что потоки работают параллельно.

Сначала я столкнулся с ограничениями размера, прежде чем он действительно мог работать в течение длительного времени, но теперь, когда я изменил его на SafeLong и избавился от всего, что держит голову, он генерировал простые числа до 100 000 000 для последние 10-20 минут (довольно медленно, да, но это не главное).

Дело в том, что теперь, когда он может работать некоторое время, я заметил, что мой процессор использует около 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
...