我如何使用可运行对象在单例中工作?

How do I use a runnable to do work in a Singleton?

我有一个关于使用 运行nable 在单例中工作的问题。

我有一个 EventCoordinator class,它是一个单例,因为它处理所有事件(并且因为我的任务要求我这样做)。 事件被添加到这个协调器中,稍后将被处理。 事件必须在不同的线程中处理,其中 运行 获取队列中的事件并处理它们。 start 方法应该启动一个新线程,该线程使用 运行.

获取队列事件
final public class EventCoordinator implements Runnable {

    protected final static EventCoordinator coordinator = new EventCoordinator();
    protected static LinkedList<QueueItem> queue = new LinkedList<QueueItem>();    
    private EventBroker() {
    }

    private class QueueItem {
        protected Event event;


        public QueueItem(Event event) {
            this.event = event;
        }
    }

    public static EventCoordinator getEventCoordinator () {
        return coordinator;
    }

    public void addEventObserver(EventObserver o) {
        //adds listeners to the coordinator
    }



    void addEvent(EventPublisher source, Event e) {
            QueueItem queueItem = new QueueItem(e, source);
            synchronized(this) { queue.add(queueItem); }
    }


    public void run() {
        // Process items from the queue
    }

    public void start() {
        // start a new thread that processes items of the queue
    }

}

但我对 运行nables 的理解是,当您创建 thread = new Thread(New EventCoordinator) 时,您会创建一个新的 EventCoordinator 对象,因此不再在同一个队列上工作。 那么如何使用 运行nable 来完成队列的这项工作呢?我是否使队列静态?我是否实现了从队列中添加和删除项目的方法,我是否在 getEventCoordinator 返回的协调器上调用它们?

尝试采用下一种方式(简单的单例实现):

public static EventCoordinator getEventCoordinator () {
    if (coordinator == null) {
         coordinator = new EventCoordinator();
    }
    return coordinator;
}

thread = new Thread(EventCoordinator.getEventCoordinator())

您可以从 start 方法启动匿名线程,在匿名线程的 运行 方法中,您可以调用事件协调器的 运行 方法,该方法将实际处理队列。如果你移除了事件协调器的运行nable接口,你就不必调用事件协调器的运行方法,队列处理可以直接在匿名线程的运行方法中完成。可能存在处理或从队列中删除元素和向队列中添加元素同时发生的情况。您将不得不使用同步块或一些锁来处理那里的并发性。

您想按照罗曼所说的去做:

public static synchronized EventCoordinator getEventCoordinator() {
    if (coordinator == null) {
         coordinator = new EventCoordinator();
    }
    return coordinator;
}

这样当你调用 getEventCoordinator() 时,你只会得到一个实例......你不想使用 thread = new Thread(new EventCoordinator()) 因为这违背了单例的目的。

当您在 start() 方法中调用 thread = new Thread(EventCoordinator.getEventCoordinator()) 时,它将使用单例实例作为 Runnable 创建线程。然后只需在 EventCoordinator.

run() 方法中定义您要如何处理队列项目

话虽如此,单例的 "preferred" 方法(根据 Joshua Bloch 的 Effective Java)是使用具有单个元素的枚举。如果你保持原样,你至少应该让你的 coordinator 字段 private 使用像 Roman 提供的 public 访问器方法。