如何将事件异步发送到所有侦听器/用户?

时间:2018-07-26 04:21:41

标签: java multithreading asynchronous

我们有广播服务,其中维护着一个收听者列表。广播者调用的方法被阻止。如何将其转换为异步或以非阻塞方式将事件发送给所有侦听器。为每次调用创建线程是唯一的方法吗?

public class EventBroadCaster {
List<Listener> allListeners = new ArrayList();

private void sendEventToAll() {
    for(Listener listener:allListeners)
        listener.accept(String event);
}
}

public interface Listener {
    public void accept(String event);
}

结构是这样的,问题是accept(String event)方法被阻塞,EventBroadCaster必须等到一个侦听器的接受完成后才能调用另一个侦听器的接受。 有没有办法使accept方法立即返回?

allListeners中可以包含100个侦听器,不想为每个接受创建100个线程。

1 个答案:

答案 0 :(得分:1)

您可以使用

String event = "wow events are strings";
allListeners.stream().parallel().forEach(l->l.accept(event));

或者您可以显式使用ExecutorService。

ExecutorService service = Executors.newFixedThreadPool(8);
...
...

List<Callable> tasks = allListeners.stream().map(l->{ l.accept(event); return l;}).collect(Collectors.toList());

service.invokeAll(tasks);

这将阻塞,直到通知每个人为止,但它将并行通知。可以避免阻塞的变化很多。

一个这样的例子,尽管不建议使用,但是会被抛诸脑后。

allListeners.forEach(l->service.execute(()->l.accept(event)));

这将停止广播方法的阻塞,但是如果太多的接受导致阻塞,则所有线程都可能陷入困境。

我认为实际的解决方案是修复accept方法。与EDT(事件分配线程)的工作方式类似。您可以让ActionListener花费很长时间,但这会导致gui暂停。取而代之的是让动作侦听器生成一个任务,这样EDT不必等待。

此外,您可能会研究RxJava。