JavaFX, Datenbank und Thread's

Guten Tag

Ich bin an einer Software die mehrere “Teilnehmer” (Datenbank, Roboter SPS) hat. Diese werden über die Software miteinander kommunizieren.

Soweit funktioniert alles, nur die Datenbankanbindung läuft noch über den JavaFX Thread. Was natürlich die Software für den Benutzer einfriert.

Es gibt circa 20 Datenbankzugriffe, würdet ihr für jede Abfrage einen neuen Thread starten, oder ist es besser einen Datenbankthread zu machen und alle Anfragen über diesen zu steuern?

Vielen Dank schonmal

Gruss

Letzeres, das ist einfacher und „besser“: dann sind - aus Sicht des einen Clients - die Daten wenigstens halbwegs konsistent…

Wenn du z.B. UPDATE - SELECT - UPDATE - INSERT - SELECT in 5 Threads laufen lässt, erfordert dass doch gewisse Annahmen über die Isolationslevels, was der User zu sehen bekommt etc.

Frage: Ist das programmatisch oder geht es um „Mausklick → Datenbankzugriff -->GUI-Update → Mausklick → Datenbankzugriff ->…“?

etwas komischer Focus auf die Datenbankzugriffe, welchen Zweck erfüllen die denn?
es muss doch auch irgendeine Logik dahinter stehen die etwa die Ergebnisse dann in der ‚Software‘ mit JavaFX-Bezug verarbeitet (= in der graphischen Oberfläche anzeigt?)

ob dabei Datenbankzugriffe vorkommen (oder Festplatte oder Netzwerk oder sekundenlange Berechnungen) ist eigentlich nebensächlich,
diese fachlichen/ anwendungslogischen Aktionen gehören, wenn sie lange dauern und eine GUI blockieren, in einen nebenläufigen Thread, richtig

Priorität sollte auf einen (oder je nach Nutzer/ Aktionen mehrere solche) Thread zur Bearbeitung der Aktion liegen,
mit Datenbankzugriffen hat das wenig zu tun,
und darin/ dabei/ dafür noch einen extra Thread für Datenbankzugriffe ist mir nicht vertraut, was macht solange der Thread, der auf die Ergebnisse wartet?

wie die nebenläufige Arbeit weiter organisiert wird, ob sich 20 DB-Anfragen oder sonstige Einzelaktionen parallel in mehreren Threads ausführen lassen oder nicht, ist die nächste Frage,
sind die denn alle voneinander unabhängig?
falls es durchführbar ist und sich der Aufwand lohnt, dann natürlich gerne,

pauschal für jeden Datenbankzugriff (ein weites Feld) eigener Thread wohl kaum, aber da muss man auch nicht drüber reden,
einfach mal entsprechend bauen und anschauen was draus geworden ist, Unterschied zu anderen Varianten,
wenn Erfolg zu sehen, dann sicher auch erklärbar durch die aktuelle Situation

edit:

bedeuten ‚20 Datenbankzugriffe‘ zufällig 20 längerfristige Aktionen, die man in der GUI auswählen kann, Buttons & Co.?
Standard dürfte bei jeder Aktion ein eigener neuer Thread sein,
aber wenn bereits eine alte Aktion läuft dann muss natürlich entschieden werden wie die beiden miteinander harmonieren

nur einen Thread zur Bearbeitung zu haben und die neue Aktion als Aufgabe dort zur Abarbeitung alsbald abzulegen kann dabei sinnvoll sein, ja,
je nachdem was man will, läßt sich vielleicht auch unabhängig abarbeiten

[QUOTE=Bleiglanz]Letzeres, das ist einfacher und “besser”: dann sind - aus Sicht des einen Clients - die Daten wenigstens halbwegs konsistent…

Wenn du z.B. UPDATE - SELECT - UPDATE - INSERT - SELECT in 5 Threads laufen lässt, erfordert dass doch gewisse Annahmen über die Isolationslevels, was der User zu sehen bekommt etc.

Frage: Ist das programmatisch oder geht es um “Mausklick --> Datenbankzugriff -->GUI-Update -> Mausklick -> Datenbankzugriff ->…”?[/QUOTE]

Sehr guter Einwand. Theoretisch könnten 5 Threads gleichzeitig eine Datenbankanfrage stellen…

Unten habe ich ein Beispiel wie ich die Kommunikation zum Roboter handle. Theoretisch könnte ich den Datenbankzugriff genau gleich machen, sprich den Task in einer Schleife laufen lassen und mit Bits die entsprechende anfrage stellen. So wäre der Datenbankzugriff immer Sequenziell.

	 * Startet den Task
	 */
	@Override
	protected Object call() {

		while (true) {
			if (!anmeldungOK.get()) {
				if (connect) {
					verbinden();
					connect = false;
				}
			}

			if (disconnect) {
				try {
					proxy.close();
				} catch (IOException e) {
					log.error("Bluebotics | Probleme mit disconnect: " + e.getMessage());
					disconnect = false;
					anmeldungOK.set(false);
				}
				disconnect = false;
				anmeldungOK.set(false);
			}
			
			// Ueberwachung starten
			if (proxy.isOpen()) {
				getPosition();
			}

			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				log.error("Bluebotics | Probleme mit Thread.sleep: " + e.getMessage());
			}
		}
	}```

*** Edit ***

[QUOTE=SlaterB;120923]etwas [..][/QUOTE]

JavaFX Visualisiert die Datenbank und die Roboter fahren gemäss der Datenbank zu ihren Zielen. Wenn der Roboter eine Datenbankanfrage stellt, wartet er bis die Antwort kommt, muss er auch damit er zum nächsten ziel fahren kann. 

hmmmmm, Theoretisch müsste ich die Anfragen die die GUI an die Datenbank stellt in einem eignen Thread laufen lassen. Alle anderen könnten in den entsprechenden Roboter Threads laufen. Dort spielt es auch keine Rolle wenn der mal 2 Sekunden steht. Und die GUI hat nicht die gleichen Abfragen wie die Roboter...

in deinem Code ist Zeile 20+21 übrigens obsolet, damit allgemein etwas schädlich,
hinter dem catch dasselbe wird auch ausgeführt, doppelt


was dauert im Moment eigentlich so lange? klingt nach Anfang des Projekts, gibt es da schon riesige Datenmengen? Suche nach Wegen?

wenn die GUI nur zur Kontrolle/ Anzeige der Bewegung von Robotern gedacht ist, was dauert bei deren Anfragen so lange?

Die Datenbank steht nicht im Hause. Sondern irgendwo ein paar Kilometer weg. Und das dauert nun mal ein wenig… Zudem werden immer drei Abfragen gestellt, (connect, anmelden,abfrage), das ist eine Vorgabe des Kunden…

Danke für den Tipp, ich war falsch in meiner Annahme das der Code nach dem Catch bei einem Fehler nicht mehr ausgeführt wird.

Aktuell ist die Ausführung der Software immer noch über Eclipse, was sicherlich nicht zur Geschwindigkeitserhöhung beiträgt.

Ich werde nun die Abfragen die vom GUI kommen in einen Thread auslagern, dies ist Ablauftechnisch kein Problem. Die Abfragen von den Robotern lasse ich in den ihren Threads laufen.

Ich habe nun ein kleines Beispiel gemacht, wie ein Thread in einer Schlaufe läuft und nach zwei Sekunden ein Dialog öffnet.

Es wäre schön wenn jemand sich das anschauen könnte und mir sagt ob das Praktikabel ist so:


import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.TextInputDialog;
import javafx.stage.Stage;

public class TaskTest extends Application {

	private Thread t1;
	
	private TextInputDialog dialog;

	private int zaehler;

	private Optional<String> resultat;

	@Override
	public void start(Stage arg0) throws Exception {
		System.out.println("Start Java FX");

		initDialog();
	}

	/**
	 * Konstruktor
	 */
	public TaskTest() {
		t1 = new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {

					System.out.println("Task 1 läuft");

					zaehler++;

					if (zaehler > 2) {
						Platform.runLater(new Runnable() {
							@Override
							public void run() {
								if (!dialog.isShowing()) {
									System.out.println("Dialog geöffnet");
									resultat = openDialog();
								}
							}
						});
					}

					if (resultat != null) {
						if (resultat.isPresent()) {
							System.out.println("OK gedrückt");
						}
					}

					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		});

		t1.setName("t1");
		t1.start();

	}

	private void initDialog() {
		dialog = new TextInputDialog("walter");
		dialog.setTitle("Text Input Dialog");
		dialog.setHeaderText("Look, a Text Input Dialog");
		dialog.setContentText("Please enter your name:");

	}

	private Optional<String> openDialog() {
		return dialog.showAndWait();
	}

	// Main
	public static void main(String[] args) {
		launch(args);
	}

}

wer erzeugt wann TaskTest-Objekte?
ist dessen Eigenschaft eine Application zu sein wichtig?
passiert das als eine Aktion in der GUI, deswegen Thread nötig?

das Hin und Her mit dem Dialog scheint nicht ganz nötig zu sein, der Thread könnte den Dialog auch selber erstellen,

                        if (resultat.isPresent()) {```
für `Optional<String> resultat` dürfte das Optional ad absurdum führen, 
aber hier durch den Dialog auch vorgegeben, musst du ja noch nicht optimal kennen

Der Thread ist für einen Kommunikation zuständig.

Die Appliaktion ist die GUI in JavaFX.

Da die Kommunikation ständig läuft (Lifebit, usw…), und ich trotzdem Interaktionen vom GUI diesem Thread übergeben muss, ergibt sich ein solches Konstrukt.

Ein Dialog kann nicht von einem normalen Thread geöffnet werden in JavaFX?!?

                        if (resultat.isPresent()) {```

Das kommt daher weil der Thread auf die Antwort des Dialogs wartet.

wenn es da unsichtbare Regenn gibt, ok, in meinem bekannten Swing mit Dialogen ja auch genug,

bei der Erzeugung wird aber nichts von der Application-Klasse genutzt,
nur new TextInputDialog(), was theoretisch jeder Thread kann

[QUOTE=SlaterB]wenn es da unsichtbare Regenn gibt, ok, in meinem bekannten Swing mit Dialogen ja auch genug,

bei der Erzeugung wird aber nichts von der Application-Klasse genutzt,
nur new TextInputDialog(), was theoretisch jeder Thread kann[/QUOTE]

        return dialog.showAndWait();
    }```

Das hir kann nur die Applikatione. Während dem 

new TextInputDialog

 vom Kommunkationsthread aus geführt wird