Parallele Aktionen in Java FX richtig durchführen.

jCoder1984

Aktives Mitglied
Hallo

Ein Klassiker (wahrscheinlich). Ich möchte in einer JavaFX Anwendung über einen Menu Punkt Daten aus einer CSV Datei importieren. Die CSV Datei besteht aus ca 20 Zeilen. Nach jeder soll sich eine ListView füllen. Was passiert : Wenn ich den Import starte kann ich nichts anderes unternehmen, da der MenuButton quasi einfriert. Am Ende (nach dem Improt) wird die Liste dann komplett dargestellt. Nun natürlich meine Frage, wie kann man dies etwas eleganter lösen. Hier mal ein Auszug aus dem GUI Handler Code :
Java:
    @FXML
    private void handleCSVImport() {
    Association association = new CommonAssociation("");
    Season season = new CommonSeason(LocalDate.of(2017, 01, 01), LocalDate.of(2018, 01, 01));

    Task<Void> importerTask1 = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
        CSVImporter importer = new CSVImporter(
            new File(getClass().getClassLoader().getResource("Spielplan_Kreisliga_Frauen_Staffel_2.csv").getFile()), association, season);
        DataManager.getInstance().importData(importer);
        return null;
        }
    };

    Task<Void> importerTask2 = new Task<Void>() {
        @Override
        protected Void call() throws Exception {
        CSVImporter importer2 = new CSVImporter(
            new File(getClass().getClassLoader().getResource("Spielplan_Landesliga_Frauen_Staffel_2.csv").getFile()), association,
            season);
        DataManager.getInstance().importData(importer2);
        return null;
        }

    };

    Platform.runLater(importerTask1);
    Platform.runLater(importerTask2);
    }

Vielen Dank für eure Hinweise
 
Der Billigste und nicht ganz saubere Weg: Schmeiss Platform#runLater raus, denn dass zwingt die Tasks, auf dem UI-Thread zu laufen. Daher das Einfrieren.

Variante 1: Verwende new Thread(task).start(); für deine Aktion
Problem: unkontrollierbare Anzahl an Threads.

Variante 2: ExecutorService: z.B.
Java:
Executor ex = Executors.newFixedThreadPool(poolSize); // im Constructor oder als Dependency einfügen
ex.execute(task);
// nicht vergessen #shutdown aufzurufen, wenn du den Executor nicht mehr brauchst!
// bitte API lesen!

Variante 3: Mal nach JavaFX-Service suchen, dort wird intern schon ein Executor vorbereitet und du kannst die dort definierten Task x-mal abspielen und dich auf die Änderungen des Status des Service registrieren.
Den Service am besten irgendwo als Singleton definieren und per Dependency Injection im Menü verwenden.
 
Sorry. War in den Ferien... 🙂 Ich hatte den Satz begonnen zu schreiben, eh ich ihn voll durchdacht habe... Sorry.

Eigentlich sollte es umgekehrt sein: Erst Platform#runLater raus, und dann kommt der nicht so saubere Teil, die Runnable einfach einem Thread zu übergeben.
 

Neue Themen


Zurück
Oben