tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
1
ZUGRIFFE
396
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von Billie
    Billie Billie ist offline Mitglied Platin
    Registriert seit
    Jan 2003
    Ort
    Arzl im Pitztal (Tirol)
    Beiträge
    510
    Hellas!

    Also, ich möchte nur sichergehen dass ich richtig gehe.

    Angenommen wir registrieren einen Listener auf einem Subject, als Beispiel einen Wecker:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    public class AlarmClock extends Thread {
     
        private List<IWakeUpListener> listeners = null;
     
        private long sleep = 0L;
     
        public AlarmClock(final long sleep) {
            this.sleep = sleep;
            listeners = new ArrayList<IWakeUpListener>();
        }
     
        private void notifyListeners() {
            synchronized (listeners) {
                for (IWakeUpListener listener : listeners) {
                    listener.wakeUp();
                }
            }
        }
     
        public void addWakeUpListener(IWakeUpListener e) {
            synchronized (listeners) {
                listeners.add(e);
            }
        }
     
        public void removeWakeUpListener(IWakeUpListener e) {
            synchronized (listeners) {
                listeners.remove(e);
            }
        }
     
        @Override
        public void run() {
            try {
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
            }
            notifyListeners();
        }
    }

    und eine schlafende Person als Listener die nach einer Sekunde vom Wecker geweckt wird:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    public class SleepingPerson implements IWakeUpListener {
     
        private AlarmClock clock = null;
     
        private SleepingPerson() {
            clock = new AlarmClock(1000L);
            clock.start();
            clock.addWakeUpListener(this);
     
        }
     
        @Override
        public void wakeUp() {
            System.out.println("I'm awake");
            clock.removeWakeUpListener(this);
        }
     
        public final static void main(String args[]) {
            SleepingPerson person = new SleepingPerson();
     
        }
    }

    Also der AlarmClock-Thread ist der selbe Thread der die schlafende Person weckt (wakeUp()) und gleichzeitig der Thread, der den Listener wieder entfernt.

    Wird jetzt die Klasse SleepingPerson über die main-Methode gestartet, bekommen wir eine ConcurrentModificationException obwohl alle Zugriffe auf die Listener in der AlarmClock synchronisiert erfolgen.

    Ist es jetzt richtig dass das Problem die foreach-Schleife in AlarmClock.notifyListeners() ist? Um genau zu sein, ist das Problem der Iterator der intern von der foreach-Schleife verwendet wird und durch ein removeWakeUpListener natürlich nicht aktualisiert wird?

    Ist somit folgende (funktionierende) Variante eine gute Lösung:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    
        private void notifyListeners() {
            synchronized (listeners) {
                for (int i = 0; i < listeners.size(); i++) {
                    IWakeUpListener listener = listeners.get(i);
                    listener.wakeUp();
                }
            }
        }

    Ich nehme an der Zugriff auf die Liste muss trotzdem immer synchronisiert erfolgen, ansonsten gibt es irgendwann eine ArrayIndexOutOfBoundsException?

    Beste Grüße,
    Billie
     
    Fann Ég Fjalli Fallega Steina
    Faldi Dá Alla Vildi Deim Leyna
    Huldi Dar Hellisskúta Heillasteina
    Alla Mína Una eth slegu Óskasteina

  2. #2
    wakoz wakoz ist offline Mitglied Gold
    Registriert seit
    Apr 2010
    Beiträge
    114
    Dein Problem hat nichts mit dem Observer zu tun!

    du arbeitest auf einer liste die einen iterator hat und diesen benutzt und das kann die foreach nicht!

    Beispiel:

    Die Foreach erzeugt am Anfang einen Size parameter der nicht wieder verändert werden kann, dieser wird mit der listen size befüllt. Und wenn du nun einen wert aus der liste löscht ist die liste die du liest kürzer als die listen größe, die die schleife kennt!
    bei den Schleifen Durchläufen würdest du irgendwann ans ende kommen wobei die schleife weiter lesen will. ArrayOutOfBounds das fängt die schleife rechtzeitig ab, undzwar mit der Exception die du bekommst!

    was auch ein sauberes verhalten ist!

    Nun müsstet du das problem haben das wenn du einen wert löscht dein counter auf den eigentlich übernächsten wert zeigt und nicht auf den nächsten, da du ja mitten drin einen wert löscht und alle nachfolgenden aufrücken.
     

Ähnliche Themen

  1. Observer pattern / Mootools / jQuery
    Von Inchtabokatables im Forum Javascript & Ajax
    Antworten: 2
    Letzter Beitrag: 23.10.11, 22:27
  2. [Design Pattern] Verhaltensmuster: Observer
    Von Thomas Darimont im Forum Design Patterns + Tipps & Tricks für Java
    Antworten: 0
    Letzter Beitrag: 03.05.11, 00:02
  3. Observer Pattern
    Von chuvak im Forum Java Grundlagen
    Antworten: 6
    Letzter Beitrag: 13.08.10, 13:06
  4. Observer Pattern
    Von tsluga im Forum Javascript & Ajax
    Antworten: 1
    Letzter Beitrag: 28.04.10, 16:05
  5. Threadübergreiffendes Observer Pattern
    Von eagle im Forum Java
    Antworten: 2
    Letzter Beitrag: 13.09.05, 16:13