我需要指定一种适合于高并发应用程序的语言(用于工业自动化目的,其要求类似于分布式在线游戏)。
假设一个case c依赖于两个变量a和b。我们的代码应该是这样的(在Javascript中):
if (a && b){
c();
}如果a是由不同的事件设置的,那么代码就会变得稍微复杂一些:
on('a', function(a){
if (a && b){
c();
}
});如果a和b都是由两个不同的事件设置的,事情就会变得更加复杂。一种解决方案可能是使用signal库:
branch = new SignalBranch()
signal1 = branch.add()
on('a', function(a){
if (a) {
signal1.go()
}
})
signal2 = branch.add()
on('b', function(b){
if (b) {
signal2.go()
}
})
branch.joined(function(err, signals){
c()
})另一种方法是使用Promise:(取自this site的示例)
var signal1 = new Promise(function(resolve){
on('a', function(a){
if (a) {
resolve()
}
})
})
var signal2 = new Promise(function(resolve){
on('b', function(b){
if (b) {
resolve()
}
})
})
Promise.all([signal1, signal2]).then(function(data) {
c();
});正如所见,实现(因此可读性)变得越来越复杂,使得阅读代码变得更加困难。
如何在Elixir中以干净的方式实现相同的任务(通过a和b信号触发c事件)?
发布于 2019-09-16 08:32:31
这真的取决于你的用例。但这里有一个可能的解决方案。
您可以使用:gen_event发出a和b的信号。然后,您可以让一些GenServer负责操作c侦听发出的事件。一旦您的GenServer收到关于a和b正在完成的两条消息,您就可以执行c操作了。您的代码将如下所示。
defmodule EventTest.EventManager do
def notify(event) do
:gen_event.notify(__MODULE__, event)
end
def register(ref) do
:gen_event.add_handler(__MODULE__, ref, [])
end
end
defmodule EventTest.EventConsumer do
@behaviour :gen_event
def init(_) do
state = %{
a: false,
b: false
}
{:ok, state}
end
def maybe_c(%{a: true, b: true}) do
# Do the thing
IO.puts "C COMPLETED!"
end
def maybe_c(_), do: nil
def handle_event(event, state) do
new_state = %{ state | event => true }
maybe_c(new_state)
{:ok, new_state}
end
def handle_call(msg, state) do
IO.inspect msg, label: "Unexpected Message"
{:ok, :ok, state}
end
end然后,在某个地方,您只需要将EventTest.EventConsumer注册到EventTest.EventManager。在按任意顺序调用EventTest.EventManager.notify(:a)和EventTest.EventManager.notify(:b)之后,您将看到执行c操作的输出。在这种情况下,它只是打印到屏幕上。
这样做的好处是,如果您需要在某个任意的时间范围内完成a和b,以便动作c完成,您可以根据需要发送消息来重置:a或:b密钥。
发布于 2019-09-17 02:34:17
另一种解决方案是使用Task.async/1和Task.await/2。基本上,您可以独立地启动这两个进程,然后等待它们都完成。
task1 = Task.async(fn () -> Process.sleep(2000) end)
task2 = Task.async(fn () -> Process.sleep(2000) end)
[task1, task2] |> Enum.each(&Task.await(&1))根据事件的触发方式,您可以使用receive/1进行阻塞,直到事件在另一个进程中发生并发送一条消息。有关发送和接收消息的简单概述,请参阅https://elixir-lang.org/getting-started/processes.html#send-and-receive。
https://stackoverflow.com/questions/57948654
复制相似问题