Homepage von Jean-René Thies — Projekte & Tools rund um Java, Groovy, Grails, PHP, Scala, MySQL...
    « JPEG ResizerCatchUp released! »

    CatchUp - hinter den Kulissen

    Permalink 18.02.09 20:53, von jrt, Kategorien: Project Plaza, Java, Groovy & Grails , Schlagworte: catchup, groovy, java, podcast

    Das CatchUp-Projekt läuft seit rund vier Monaten und ist mittlerweile bei Version 3.6 angekommen. Mit den letzten Änderungen hat der Podcast Reciever nochmal an Tempo und Stabilität zugelegt, gleichzeitig bin ich zwangsläufig an Erfahrungen reicher geworden.

    CatchUp ist stark auf Multithreading ausgelegt, und das bringt einige Herausforderungen mit sich. Wer sich dafür interessiert, kann gerne mal einen Blick unter die Haube werfen und sich ein paar Lösungen anschauen.

    Fortsetzung:

    RSS-Feeds laden und verarbeiten
    Groovy fasziniert mich schon seit Monaten, und den XMLSlurper finde ich so phänomenal, dass ich ihn zum Herzstück von CatchUp gemacht habe.

    Wenn man sich den RSS-Feed eines Podcast genauer anschaut, findet man schnell die interessanten Elemente: item, title, pubDate und enclosure.
    Hier ein verkürztes Beispiel:

    XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <channel>
      <title>Der Titel des Podcast</title>
      <description>Eine Beschreibung des Podcasts</description>
      <item>
        <title>Titel der Episode</title>
        <link>http://www.website.com/podcast/</link>
        <pubDate>Thu, 12 Feb 2009 13:52:12 +0000</pubDate>
        <description>Hier kann ein längerer Beschreibungstext stehen.</description>
        <enclosure url="http://www.website.com/podcastdatei.mp3" length="30844507" type="audio/mpeg"/>    
      </item>
      <item>
        <title>Nächste Episode (...)</title>
      </item>
    </channel>

    Das auszulesen ist dank Groovy extrem einfach:

    def feedxml=new XmlSlurper().parse(pod.getUrl())

    Wobei pod.getURL() die Webadresse des Podcast liefert.
    Anschließend läuft eine Schleife für jedes item-Element:

    Code:

    for(episode in feedxml.channel.item){
      Episode e=new Episode()
      e.pubDate=episode.pubDate
      e.title=episode.title
      e.description=episode.description
      e.enclosureUrl=episode.enclosure.@url
    }

    Hier wird jedes item-Element als "episode" behandelt und Stück für Stück einem eigenen Episode-Objekt zugeordnet. Zu beachten: das @-Zeichen, um das XML-Attribut "url" zu bekommen.

    Die komplette Klasse UpdateFeedJob kann man sich hier anschauen.

    Warteschlangen und eingeschränkte Parallelität für mehrere Threads

    Ein paar Feeds auszulesen geht schnell und macht keine größeren Probleme. Etwas schwieriger ist es, Warteschlangen für Downloads, Prozesse und Kopiervorgänge zu erstellen und dafür zu sorgen, dass sinnvolle Paralellisierung stattfindet. Zwei gleichzeitige Downloads sind o.k., und während der Downloads kann auch MP3Gain im Hintergrund die Lautstärke von MP3-Dateien anpassen. Kopiervorgänge auf den MP3-Player sollten nur nacheinander passieren. Wie geht das?

    In den ersten CatchUp-Versionen habe ich noch Quartz eingesetzt, was grundsätzlich funktioniert, aber nicht optimal ist. Quartz ist eigentlich eine Zeitsteuerung für Threads, keine Warteschlangenverwaltung. Inzwischen setze ich ExecutorServices aus dem Paket java.util.concurrent ein. Ein ExecutorService passt genau:


    ExecutorService feedUpdater = Executors.newFixedThreadPool(2);

    Und schon kann man mit feedUpdater.execute(new UpdateFeedJob(...)) beliebig viele Threads an "feedUpdater" übergeben. Der ExecutorService garantiert, dass maximal zwei davon gleichzeitig laufen und der Rest wartet, bis er an die Reihe kommt.
    Details dazu sind in der Klasse TaskController zu finden.

    Einfrieren der Benutzeroberfläche verhindern

    Noch in Version 3.5 kam es manchmal zu kompletten Blockaden der Swing-Benutzeroberfläche - und die Fehlerquelle konnte ich einfach nicht finden. Deadlocks? Race conditions? Aber wo?
    Nach längeren Recherchen fand ich den Hinweis, dass auch Probleme bei Netzwerkverbindungen diesen Effekt haben können und unternahm einen Versuch mit Spin. Und siehe da: seitdem kein einziger "Freeze" mehr. Verblüffend einfach und effekiv! Vor dem Einsatz unbedingt die Beschreibung lesen.

    Einen Kommentar hinterlassen »

    Noch kein Feedback

    Einen Kommentar hinterlassen


    Ihre E-Mail-Adresse wird nicht auf dieser Seite angezeigt.

    Ihr URL wird angezeigt.
    (Zeilenumbrüche werden zu <br />)
    (Name, E-Mail-Adresse & Webseite)
    (Benutzern erlauben, Sie durch ein Kontaktformular zu kontaktieren (Ihre E-Mail-Adresse wird nicht weitergegeben))

    ©2010 by Jean-René Thies

    Kontakt |