2016-02-26 87 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方法直接執行隊列處理。可能會出現這樣的情況,即同時處理或從隊列中移除元素並添加隊列中的元素。您將不得不使用同步塊或某個鎖來處理併發。