Multithreading 多线程状态单子

Multithreading 多线程状态单子,multithreading,scala,monads,state-monad,Multithreading,Scala,Monads,State Monad,假设我有一个有状态的客户机smth trait Client { case class S(connection: Connection, failures: Int) // Connection takes 10 seconds to create def fetchData: State[S, Data] // Takes 10 seconds to fetch } 我想使它有状态,因为创建连接的成本很高(所以我想缓存它)+我有故障计数来指示一行中是否有太多的故障,然后基本上重新创

假设我有一个有状态的客户机smth

trait Client {
  case class S(connection: Connection, failures: Int) // Connection takes 10 seconds to create
  def fetchData: State[S, Data] // Takes 10 seconds to fetch
}
我想使它有状态,因为创建连接的成本很高(所以我想缓存它)+我有故障计数来指示一行中是否有太多的故障,然后基本上重新创建连接

我从State monad中了解到,它实际上应该在一个线程上进行计算,在该线程上按顺序链接不可变的状态。在这种情况下,我负担不起,因为我的fetch操作需要花费大量的时间,而我所需要的只是快速读取状态,从那里使用连接来启动昂贵的异步调用。另一方面,我无法使其处于
状态[S,Task[Data]]
,因为如果Task
获取数据
失败,我需要在
S
中修改
失败。所以我把客户端修改为

import fs2.Task

trait Client {
  case class S(connection: Connection, failures: Int) // Connection takes 10 seconds to create
  def fetchData: StateT[Task, S, Data] // Takes 10 seconds to fetch
}
问题是我可以想出一些幺半群,它可以添加与初始状态无关的状态。例如,如果我有
S1->(S2,数据)
S1->(S3,数据)
,我仍然可以添加S2和S3以达到最终状态,而不管在-S2或S3之前发生了什么

现在我有了一种Java服务器(Thrift),它使用这个处理程序。我还没有深入了解它是如何精确工作的,但是让我们假设它侦听传入的连接,然后生成一个线程来处理数据检索。因此,在我的例子中,我希望阻止线程,直到
任务
完成:

 class Server(client: Client) {
    def handle: Data {
       run(client.fetchData)
    }

    private var state: S = Monoid[S].mempty

    private def run(st: State[S, Data]): Data {
      val resTask: Task[(S, Data)] = st.run(state)
      val (newState, res) = Await.result(resTask.unsafeRunAsyncFuture)
      state.synchonized({
        state = Monoid[S].mappend(state, newState)
      })
      res
    }
 }
我的问题是:

1) 我在这里做得对/最好吗(我的重点是效率/没有bug)

2) 我真的需要状态monad吗,还是最好使用普通var并使用它

3) 在State monad的示例中,我总是看到状态被传播到应用程序的顶层并在那里处理。但也许最好在
客户端
级别处理它,并向应用程序公开无状态接口

4) 这段代码是线程安全的,还是我应该让state成为某种类型的同步变量?我知道,在目标C中,这个行<代码>状态=幺半群[S]。MappEnter(状态,NeWSTATE)如果在赋值中间,从另一个线程读取该状态,则可能崩溃。