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:
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?
Hier der Task selbst:
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".
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".