"Callback"-Mechanismus für asynchrone Kommunikation

  • Hallo zusammen,


    ich haette da mal wieder eine Frage zu meiner Klassenarchitektur:


    Ausgangssituation:
    Ein Objekt meiner Klasse AppModel besitzt einen bestimmten Datenstand (mehrere Datensätze, jeweils mit Versionsnummer)
    Ein entfernter Server besitzt ebenfalls einen bestimmten Datenstand (analog oben)
    Zwischen beiden erfolgt eine Kommunikation über ein eigenes, asynchrones Protokoll (via Socket), z.B.:


    - App kann Versionsstand anfragen (sendet 1 Botschaft), "irgendwann" kommt die Antwort.
    - App kann Datenstand aktualisieren (sendet je nach Umfang des Datenstandes 1-x einzelne Botschaften), "irgendwann" kommt Antwort "ok" o.ä.


    Ziel:
    Abgleich der Datenstände realisieren.


    Was besteht bisher:


    - Ich habe eine Klasse Jobs definiert, die in einer ArrayList alle zu versendenden Botschaften enthält. Außerdem weiß ein Job, auf welche Antwortbotschaft er zu warten hat.


    - Mehrere Jobs verwaltet der JobHandler. Er übernimmt das eigentliche Senden (holt sich die erste Botschaft aus dem Job, versendet sie, und löscht sie dann aus dem Job) und Empfangen (empfängt grundsätzlich alle Nachrichten und prüft dann, ob es einen Job gibt, dessen Nachrichten komplett versendet wurden, für den aber noch keine gültige Antwort empfangen wurde).


    - Alle Objekte, die sich als Listener registriert haben, werden zB darüber informiert, dass ein Job (den sie evtl selber beim HobHandler platziert haben), abgeschlossen wurde (und was die Antwortbotschaft war).


    Soweit der Plan. In der Umsetzung hapert es momentan an einer Stelle: Auch wenn ich zB aus meinem Model heraus die Jobs beim JobHandler platziere, weiß ich nicht, mit welchem Mechanismus ich über dessen Abarbeiten informiert werden kann, ohne umständlich prüfen zu müssen, auf WELCHER Job abgearbeitet wurde.


    Was mir alternativ in den Sinn kam, aber nicht besonders sinnvoll erscheint, wäre etwas wie folgendes (Natürlich in einem seperaten Thread ausgeführt):



    Was mich daran stört ist nicht nur, dass ich mich da u.U. irgendwie blockieren könnte, sondern auch, dass es Fälle geben kann, in denen ein "Callback-Mechanismus" wie oben reichen würde, also alle Listener über das abarbeiten eines Jobs informiert würden, aber eben nicht immer... und so ein Gemische erscheint mir arg fehleranfällig...


    Ich hoffe, ihr könnt mein Problem nachvollziehen und habt ein paar Ideen für mich,


    Viele Grüße,
    FargoTof

  • Guten Morgen,


    ich habe mein Problem mitlerweile halbwegs gelöst, allerdings wirft das direkt neue Fragen auf.. :( Ich habe mir für meinen JobHandler jetzt eine private Runnable angelegt, die einfach in Endlosschleife für nacheinander für alle Jobs prüft, ob für deren aktuelle Nachricht schon bestätigt wurde und somit gelöscht werden kann:



    Der Job bleibt also so lange auf BUSY, bis er ein ACK empfangen hat, aber das nur am Rande. Problematisch wird es nun, wenn ich meinem JobHandler neue Jobs hinzufüge, also:


    Java
    public void addJob(Job job){
        jobs.add(job);
    }


    Dann kommt nämlich das durchiterieren von jobs in meiner Endlosschhleife durcheinander und es gibt eine Exception


    Code
    03-27 08:51:45.880: E/AndroidRuntime(1693):     java.util.ConcurrentModificationException
    03-27 08:51:45.880: E/AndroidRuntime(1693):     at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
    03-27 08:51:45.880: E/AndroidRuntime(1693):     at de.meineFirma.JobHandler$1.run(JobHandler.java:55)


    Ich könnte mir vorstellen, dass ich bestimmte Abschnitte als "synchronized" setzen muss, weiß aber nicht welche bzw. ob dies wirklich der richtige Weg ist (bei dem ich mir nicht wieder andere Sachen seltsam blockiere).


    Hat hier jemand Rat für mich?


    Danke und Grüße,
    FargoTof

  • Hi,


    danke, nähreres hierzu kannst du aber nicht sagen, also etwas zu deiner "Grundidee"? Problem ist aktuell ja nicht, dass ich nicht verschiedene Threads hätte, sondern vielmehr, dass ich meine ArrayList während des Iterierens verändere.


    Vllt ist ja auch das dauerhafte Iterieren als solches ein unsinniger Ansatz, allerdings wüsste ich nicht, wie ich meine Nachrichten sonst am besten abschicke (MEINE Idee ist ja, meinen Jobs nach Erhalt der "ACK"-Botschaft jeweils mitzuteilen, dass sie wieder senden dürfen, und während meines o.g. Iterierens eben darauf prüfe und wenn möglich sende).


    Grüße,
    FargoTof

  • Hi,


    mir fällt jetzt erst auf du sagst ArrayList, ist leider nicht threadsave. Probier mal einen Vector, der ist synchronized und ansonsten so ziemlich identisch.


    Mein Grundgedanke war jede Nachricht ist ein Thread der in den ThreadPool geworfen wird. Wenn der irgendwann mal Zeit und Lust hat schickt er die los und holt sich dann die nächste Nachricht die er wenn er wieder mal Zeit kriegt raus haut ...


    Gruß,
    matze

  • Hallo fargoTof


    könnte deine Listener Klasse ein eigenes Interface implementieren? zB

    Java
    public interface IJobFinished{public void jobFinished(Job foo);}



    danach müsste deine Listener Klasse einfach dieses Interface implementieren?
    Solbad der Job abgearbeitet ist ruft er auf seinem registrieren Listener .jobFinished(this)
    auf oder sowas?
    Dein Listener könnte ja auch noch eine Refernez zum Job behalten und bei
    jobFinished kontrolliere ob es derjenige ist den er gestartet hat?

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!