Я экспериментировал с использованием потоков для генерации простых чисел в 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