Как вы комбинируете несколько потоков Scalaz, так что порядок завершения сохраняется, но чередование не применяется?

var num =0
var num2 = 3333
val p2 = Process.eval {
 Thread.sleep(10000)
 Task.delay {
 Thread.sleep(10000)
 num2 = num2 + 1
 s"hi ${num2}"
 }
}.repeat.take(15)
//p2: scalaz.stream.Process[[x]scalaz.concurrent.Task[x],String] =
// Await(scalaz.concurrent.Task@5a554f1c,
//<function1>,Halt(scalaz.stream.Process$End$),Halt(scalaz.stream.Process$End$))
val p1 = Process.eval {
 Thread.sleep(2000)
 Task.delay { 
 Thread.sleep(2000)
 num = num + 1
 s"hi $num"
 }
}.repeat.take(15)
//p1: scalaz.stream.Process[[x]scalaz.concurrent.Task[x],String] = 
// Await(scalaz.concurrent.Task@7a54e904,
// <function1>,Halt(scalaz.stream.Process$End$),Halt(scalaz.stream.Process$End$))
// this interleaves them and I get disjunctions showing me their order
(p1 either p2).map(println).run.run
// this gives me the strings that are interleaved
(p1 interleave p2).map(println).run.run
</function1></function1>

Как вы получаете процесс, который является комбинацией двух Процессов, но только в том порядке, в котором они прибывают (что означает, что если левый идет дважды перед правым, это нормально, дайте левому дважды, а затем, когда справа придет его излучение потом)?

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

1 ответ

Эрик,

недетерминированный чередование реализуется в потоке scalaz через Process.wye, и на самом деле либо является одним из недетерминированных комбинаторов, использующих wye. Причина, по которой вы видите, что они чередуются влево/вправо, заключается в том, что она пытается быть честной и потому, что вы блокируете поток. Попытайтесь создать одну сторону, которая будет медленнее второй, и вы увидите, что она является недетерминированной.

Обратите внимание, что для достижения не-детерминированного поведения вам понадобятся фактически процессы, которые запускаются из двух потоков, ваш процесс p1 фактически блокирует единственный поток и как таковой в вашем сценарии порядок всегда детерминирован.

попробуйте:

val p1 = Process(1,2,3).toSource
val p2 = Process(10) fby Process.sleep(1 second) fby Process(20,30).toSource
(p1 either p2).runLog.run.foreach(println)

Это должно испускать

-\/(1)
\/-(10)
-\/(2)
-\/(3)
\/-(20)
\/-(30)

licensed under cc by-sa 3.0 with attribution.