2

注意:代码是线程安全的,换句话说,是单线程的。只有我可以将自己从听众名单中删除。

我有 1000 个不同的 ArrayLists 侦听器,我必须使用如下代码通知它们:

protected void onFlushed() {
    int size = listeners.size();
    for (int i = 0; i < size; i++) {
        listeners.get(i).onFlushed();
        int newSize = listeners.size();
        if (newSize == size - 1) {
            size--;
            i--;
        } else if (newSize != size) {
            throw new ConcurrentModificationException("List was altered while iterating! oldSize=" + size + " newSize=" + newSize);
        }
    }
}

有没有一种聪明的方法来创建一个 Notifier 类,它可以采用任何 ArrayList 的侦听器以及任何侦听器方法并为我执行下面的逻辑,或者我必须为每个侦听器方法在任何地方复制上面的代码?

我对 Java 的要求太多了吗?:(

4

2 回答 2

3

首先,我有点担心大部分代码似乎都在以一种不太安全的方式处理并发问题。考虑对访问相同侦听器列表的任何代码进行一些锁定。这样,您可以将此代码简化为:

protected void onFlushed() {
    synchronized(listeners) {
        for (FlushListener listener : listeners) {
            listener.onFlushed();
        }
    }
}

在您的代码周围重复这并不是太糟糕。话虽如此,如果出于某种原因您需要那里的逻辑,您可以创建一个类似这样的类:

import java.util.ArrayList;
import java.util.ConcurrentModificationException;

public class Notifier<T> {
    public static interface NotificationRunnable<T> {
        public void notify(T t);
    }

    private ArrayList<T> listeners;
    public Notifier() {
        listeners = new ArrayList<T>();
    }

    public void addListener(T t) {
        listeners.add(t);
    }

    public void notifyAll(NotificationRunnable<T> nr) {
        int size = listeners.size();
        for (int i = 0; i < size; i++) {
            nr.notify(listeners.get(i));
            int newSize = listeners.size();
            if (newSize == size - 1) {
                size--;
                i--;
            } else if (newSize != size) {
                throw new ConcurrentModificationException("List was altered while iterating! oldSize=" + size + " newSize=" + newSize);
            }
        }
    }
}

然后调用它的代码如下所示:

Notifier<FlushListener> notifier = new Notifier();
notifier.addListener(new FlushListener());

public void onFlushed() {
    notifier.notifyAll(new NotificationRunnable<FlushListener>(){
        public void notify(FlushListener t) {
            t.onFlushed();
        }
    });
}

甚至在实际方法中将其简化为一行:

NotificationRunnable<FlushListener> flushRunnable = new NotificationRunnable<FlushListener>(){
    public void notify(FlushListener t) {
        t.onFlushed();
    }
}

public void onFlushed() {
    notifier.notifyAll(flushRunnable);
}
于 2012-08-24T23:18:59.440 回答
2

在当前的 Java 中,无法像在函数式语言中那样传递方法,但是您可以创建Function<Domain, Range>接口并传递实现该接口的对象。

您可能会考虑使用Guava,它提供了一些类似于功能习语和列表理解的东西。

于 2012-08-24T23:21:23.800 回答