2016-02-26 3 views
1

У меня есть вопрос об использовании runnable для работы в singleton.Как использовать 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 
    } 

} 

Но, как я понимаю runnables, что при создании thread = new Thread(New EventCoordinator) вы создаете новый объект EventCoordinator и, таким образом, не работают на одной и той же очереди больше. Итак, как вы можете использовать runnable для выполнения этой работы в очереди? Я старую статическую очередь? Я реализую методы для добавления и удаления элементов из очереди и вызываю их в координаторе, возвращаемом getEventCoordinator?

+1

1) Используйте «BlockingQueue». 3) избавиться от всех «синхронизированных» блоков. 3) Вы в основном сделаны. –

+0

Почему вы не можете просто «thread = new Thread (coordinator)»? – OldCurmudgeon

+0

@Deb Какой ответ вы выбрали как лучший? Не могли бы вы найти решение? – Saidolim

ответ

2

Вы хотите делать то, что сказал Роман:

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

Таким образом, когда вы звоните getEventCoordinator(), вы только когда-либо получить, что один экземпляр ... вы не хотите использовать thread = new Thread(new EventCoordinator()) потому, что побеждает цель одноэлементного.

Когда вы вызываете thread = new Thread(EventCoordinator.getEventCoordinator()) в свой метод start(), он создаст поток, используя экземпляр singleton, как Runnable. Затем просто определите, как вы хотите обрабатывать элементы очереди в вашем run() методе EventCoordinator.

С учетом сказанного «предпочтительный» подход к одноэлементному (согласно эффективной Java от Джошуа Блоха) заключается в использовании перечисления с одним элементом. Если вы сохраните его, как это, вы должны, по крайней мере, сделать свой coordinator полем private с помощью метода доступа, такого как Roman.

+0

Удивительная, не потокобезопасная одноэлементная конструкция, очевидно, с резьбовым кодом ... –

+0

Вы правы, я просто повторил то, что сказал Роман, но я должен был уделять более пристальное внимание ... Я обновил свой ответ, включив 'synchronized'. –

1

попытаться пойти по следующему пути (простая реализация singelton):

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

и

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

Я новый для многопоточности, отличается от 'thread = new Thread (EventCoordinator.getEventCoordinator())' и 'thread = new Thread (new EventCoordinator()). Этот поток использует те же частные члены, что и новые объекты? И работает ли работа, выполняемая в ходе выполнения разными потоками, все еще полностью параллельными? – Deb

+0

Я думаю, вторая часть вашего решения работала. Однако первый из них не нужен и даже невозможен, поскольку мой конструктор закрыт. – Deb

+0

Можно вызвать частный конструктор в классе 'EventCoordinator', только не за его пределами. Это позволяет создать экземпляр singleton внутри самого класса, но не позволяет создавать другие экземпляры в других классах. –

0

Вы можете начать анонимный поток из метода запуска и в методе выполнения анонимного потока можно назвать координатор мероприятия который будет фактически обрабатывать очередь. Если вы удалите исполняемый интерфейс координатора событий, вам не придется вызывать метод запуска координатора событий, а обработка очереди может выполняться непосредственно в методе запуска анонимного потока. Может быть случай, когда обработка или удаление элементов из очереди и добавление элементов в очередь происходит одновременно. Вам придется обрабатывать параллелизм там, используя либо синхронизированный блок, либо некоторую блокировку.