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