2016-02-26 30 views
1

我有一个关于使用runnable在单身人士中工作的问题。如何使用runnable在Singleton中工作?

我有一个EventCoordinator类,它是一个单例,因为它是处理所有事件的一个(因为我的任务需要我这样做)。 事件将被添加到此协调器中,并将在稍后处理。 必须在不同的线程中处理事件,在该线程中,运行将处理队列的事件并对其进行处理。 start方法应该启动一个新的线程,该线程使用run来接收队列的事件。

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 
    } 

} 

但据我所知可运行的方式是,当你创建一个thread = new Thread(New EventCoordinator)您创建一个新的EventCoordinator对象,因而不工作在同一个队列了。 那么如何使用runnable来完成队列的这项工作呢?我是否使队列静态?我是否实现了方法来添加和删除队列中的项目,并且在由getEventCoordinator返回的协调器上调用它们?

+1

1)使用'BlockingQueue'。 3)摆脱所有'synchronized'块。 3)你基本完成了。 –

+0

为什么你不能只是'线程=新的线程(协调器)'? – OldCurmudgeon

+0

@Deb您选择哪个答案为最佳答案?你能找到解决办法吗? – Saidolim

回答

2

你想要做什么罗曼说:

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中您要如何处理队列项目。据说,单身人士的“首选”方法(根据Joshua Bloch的Effective Java)是使用具有单个元素的枚举。如果保持原样,至少应该使用像Roman提供的public访问器方法来使您的coordinator字段private

+0

真棒,非线程安全的单线程代码... –

+0

你是对的,我只是重申罗马说的,但我应该更加关注......我更新了我的答案,以包括'synchronized'。 –

1

尝试下一个方法(简单singelton实现)去:

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

thread = new Thread(EventCoordinator.getEventCoordinator()) 
+0

线程使用相同的私有成员而不是新对象的不同之处在于线程=新的线程(EventCoordinator.getEventCoordinator())和线程=新的线程(新的EventCoordinator())?并且在不同线程所调用的运行中完成的工作仍然完全平行吗? – Deb

+0

我认为你解决方案的第二部分工作。然而,第一个是不需要的,因为我的构造函数是私有的。 – Deb

+0

可以在'EventCoordinator'类中调用私有构造函数,但不在其外部。这使您可以在类本身内创建单例实例,但可以防止在其他类中创建其他实例。 –

0

你可以从你开始的方法和在匿名的线程的run方法,你可以调用事件协调员开始匿名线程将实际处理队列的运行方法。如果删除事件协调器的可运行接口,则不必调用事件协调器的run方法,并且可以使用匿名线程的run方法直接执行队列处理。可能会出现这样的情况,即同时处理或从队列中移除元素并添加队列中的元素。您将不得不使用同步块或某个锁来处理并发。