Mehrfache Ausführung desselben Threads/Tasks verhindern?

Status
Nicht offen für weitere Antworten.

Daniel_L

Bekanntes Mitglied
Hallo,

ich habe schon gesucht, aber finde mal wieder nicht die richtigen Suchbegriffe - oder es gab das Thema tatsächlich noch nicht.

Per Button-Klick starte ich einen Hintergrund-Thread, der "createLinkTask" heißt:

Code:
    /**
     * references to the task, needed for cancel operation.
     */
    createLinksTask createLinkTask;

    /**
     * This method displays the links/connection of an entry by starting
     * a background task. after the task finishes, all links from this entry
     * to other entries are display in the JTable of the JTabbedPane
     */
    private void showLinks() {
        // if no data available, leave method
        if (data.getCount(data.ZKNCOUNT)<1) return;
        // if the link-table is not shown, leave
        if (jTabbedPaneMain.getSelectedIndex()!=TAB_LINKS) return;

        // clear selections
        jListEntryKeywords.clearSelection();
        
        // cancel already running task if necessary, so we don't have more parallel tasks running
        if ((createLinkTask != null) && !createLinkTask.isDone() && !createLinkTask.isCancelled()) {
            createLinkTask.cancel(true);
        }
        
        // disable tablesorter, because this may lead to index-out-of-bound and
        // null-pointer-exceptions when running the task...
        jTableLinks.setAutoCreateRowSorter(false);
        
	Task clT = createLinks();
        // get the application's context...
	ApplicationContext appC = Application.getInstance().getContext();
        // ...to get the TaskMonitor and TaskService
        TaskMonitor tM = appC.getTaskMonitor();
        TaskService tS = appC.getTaskService();
        // with these we can execute the task and bring it to the foreground
        // i.e. making the animated progressbar and busy icon visible
        tS.execute(clT);
        tM.setForegroundTask(clT);    
    }

Nun kann es sein, dass dieser Thread durch Buttonklick erneut aufgerufen wird, bevor der alte Thread fertig ist. Meine Frage, wie kann ich das verhindern? Ich dachte, durch das obige canceln wird das bereits verhindert?

Code:
        // cancel already running task if necessary, so we don't have more parallel tasks running
        if ((createLinkTask != null) && !createLinkTask.isDone() && !createLinkTask.isCancelled()) {
            createLinkTask.cancel(true);
        }


Hier der Task selbst:

Code:
    /**
     * This Action creates the links between of the currently displayed entry with all other enries,
     * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane
     * 
     * @return the background task
     */
    @Action
    public Task createLinks() {
        return new createLinksTask(org.jdesktop.application.Application.getInstance(zettelkasten.ZettelkastenApp.class));        
    }
    /**
     * This Action creates the links between of the currently displayed entry with all other enries,
     * based on matching keywords. These hyperlinks are stored in the JTable of the JTabbedPane
     * 
     * @return the background task
     */
    private class createLinksTask extends org.jdesktop.application.Task<Object, Void> {
        createLinksTask(org.jdesktop.application.Application app) {
            super(app);
            createLinkTask = this;
        }        
        
        @Override protected Object doInBackground() {
            DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel();
            // reset the table
            tm.setRowCount(0);
            
            // variable that indicates whether a match of keywords was found
            boolean found=false;
            int cnt;
            
            // get the length of the data file, i.e. the amount of entrys
            final int len = data.getCount(data.ZKNCOUNT);

            // get the keyword index numbers of the current entry
            String[] kws = data.getCurrentKeywords();
            // if we have any keywords, go on
            if (kws!=null) {
                // create new instance of that variable
                linkedlinkslist = new LinkedList<Object[]>();
                // iterate all entrys of the zettelkasten
                for (cnt=1; cnt<=len; cnt++) {
                    // leave out the comparison of the current entry with itself
                    if (cnt==data.getCurrentZettelPos()) continue;
                    // init the found indicator
                    found = false;
                    // look for occurences of any of the current keywords
                    for (String k : kws) {
                        if (data.existsInKeywords(k, cnt)) {
                            found = true;
                            break;
                        }
                    }
                    // if we have a match, connect entries, i.e. display the number and title of
                    // the linked entries in the table of the tabbed pane
                    if (found) {
                        // create a new object
                        Object[] ob = new Object[2];
                        // store the information in that object
                        ob[0] = cnt;
                        ob[1] = data.getZettelTitle(cnt);
                        // and add that content to linked list
                        linkedlinkslist.add(ob);
                    }
                }
            }
            return null;
        }
        
        @Override protected void succeeded(Object result) {
            DefaultTableModel tm = (DefaultTableModel) jTableLinks.getModel();
            // reset the table
            tm.setRowCount(0);
            // check whether we have any entries at all...
            if (linkedlinkslist!=null) {
                // create iterator for linked list
                Iterator<Object[]> i = linkedlinkslist.iterator();
                // go through linked list and add all objects to the table model
                while (i.hasNext()) tm.addRow(i.next());
            }
        }

        @Override
        protected void finished() {
            super.finished();
            createLinkTask = null;
            jTableLinks.setAutoCreateRowSorter(true);
        }
    }

Das Problem ist, dass der List-Iterator aus der succeeded-Methode läuft, während ein zweiter Thread gestartet wird und es zu einer "java.util.ConcurrentModificationException".
 

Marco13

Top Contributor
Über Spezifika der Klassen, die du verwendest, weiß ich jetzt zwar nicht bescheid, aber ... die einfachste, gängigste und IMHO sinnvollste Lösung für so ein Problem ist i.a. den button auszugrauen, bis der Task fertig ist
button.setEnabled(false);
rechneRechneRechne();
button.setEnabled(true);
 
S

Spacerat

Gast
Hallo...

Zwei Möglichkeiten:

1. Restart der selben Instanz des Threads verhindern:
- private Member-Variable "boolean running" der Klasse hinzufügen.
- Die "start()"-Methode der Klasse überlagern. In dieser die hinzugefügte Member-Variable abfragen.
- Für den fall das sie gesetzt ist Methode verlassen ("return").
- Andernfalls "super.start()" aufrufen und hinzugefügte Member-Variable setzen.
- in den Methoden "run()" und "stop()" bzw. "interrupt()" der Klasse an geeigneter Stelle dafür sorgen, das "running" beim beenden des Threads zurückgesetzt wird.

2. Start einer neuen Instanz des Threads verhindern:
- der Klasse eine private Member-Variable der Thread-Klasse hinzufügen.
- der Klasse eine eigene "start()"-Methode hinzufügen, in welcher die neue Member-Variable auf "null" getestet wird.
- Bei "null" der Variablen eine neue Instanz des Threads zuweisen und diese starten.
- Andernfalls Methode verlassen.
- Analog dazu: Der Klasse eine "stop()"-Methode hinzufügen. ... Thread-instanz stoppen, M-V auf "null" setzen.

Die erste Methode ist meistens die bessere, weil die zweite recht viel "garbage" produziert.

cu Spacerat

@Edit: Die "start()"-Methoden nach Möglichkeit bitte "synchronized".
 

Daniel_L

Bekanntes Mitglied
Vielen Dank für die Antworten.

Zum Disablen des Buttons: Es handelt sich um ein Durchblättern durch Datensätze. Dies sollte ständig möglich sein. Die Aufgabe innerhalb des Threads dauert mal 'ne halbe Sekunde, mal 2-3 Sekunden. Und ich wollte gerne, dass beim schnellen Durchblättern der aktuelle Thread, der ja Daten für den aktuell angezeigten Datensatz bearbeitet, abgebrochen und der neue Thread statt dessen ausgeführt wird.

Aber die Idee mit der "running"-Variable ist schonmal ganz gut, um doppelte Threads zu verhindern. Leider läuft dann eben nur der alte Thread weiter, der eigentlich Daten zu einem vorigen Datensatz noch berechnet, wenn man schnell durchblättert.

@Edit: Die "start()"-Methoden nach Möglichkeit bitte "synchronized".
was meinst du damit? Ich habe den obigen Sourcecode von den NetBeans-Beispielen zur Java-Desktop-App kopiert und halbwegs verstanden, aber nicht intensiver damit auseinandergesetzt....
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Mehrfache if-else-Abfrage zusammenfassen Allgemeine Java-Themen 51
A Mehrfache XOR Verschlüsselung Allgemeine Java-Themen 11
S OOP Mehrfache Vererbung von abstrakten Klassen Allgemeine Java-Themen 7
J Fehlermeldung bei Ausführung von .jar-Datei Allgemeine Java-Themen 9
S Gibt es eine Moeglichkeit die Runtime Ausführung zu analysieren..? Allgemeine Java-Themen 7
M Webservice timeout bei Ausführung der .jar Allgemeine Java-Themen 3
L Fehler bei der Ausführung einer Jar Allgemeine Java-Themen 2
S Fehlermeldungen erscheinen erst in der Ausführung des Programms Allgemeine Java-Themen 11
A einmalige Ausführung eines Methodenabschnittes Allgemeine Java-Themen 3
E Threads Ausführung in Threads ist langsamer als ohne Threads Allgemeine Java-Themen 13
B Ungewollte mehrmalige ausführung des codes Allgemeine Java-Themen 10
H Plattformunabhänginge Ausführung einer .jar Datei Allgemeine Java-Themen 8
R Internetverbindung weg bei ausführung Allgemeine Java-Themen 3
W Deserialisierung und Ausführung Allgemeine Java-Themen 2
X Prozess-Objekt nach Ausführung der destroy-Methode null oder nicht null ? Allgemeine Java-Themen 10
J Wie die gleichzeitige Ausführung mehrerer Tasks trotz Multithreading verhindern? Allgemeine Java-Themen 2
V Parallele Ausführung Allgemeine Java-Themen 8
D Eclipse-build vs. Jar-Ausführung Allgemeine Java-Themen 3
V Ausführung Client- oder Serverseitig? Allgemeine Java-Themen 13
I Thread eine bestimmte Zeit zur Ausführung geben Allgemeine Java-Themen 2
R ClientHTTPRequest - bei mehrfacher Ausführung? Allgemeine Java-Themen 2
K Richtige JVM für jar Ausführung? Allgemeine Java-Themen 4
F JAR-Datei-Ausführung löst Fehler aus Allgemeine Java-Themen 5

Ähnliche Java Themen

Neue Themen


Oben