Je débogue du code qui a été écrit en utilisant un SwingWorker pour effectuer une combinaison de calcul numérique et de mise à jour de l'interface graphique. Le SwingWorker se bloque avec la trace de la pile suivante:Java SwingWorker suspendu
Full thread dump Java HotSpot(TM) Client VM (14.3-b01 mixed mode, sharing):
"SwingWorker-pool-3-thread-4" prio=6 tid=0x07fd7c00 nid=0x143c waiting on condition [0x0a33f000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:940)
at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:877)
at javax.swing.SwingWorker$1.call(SwingWorker.java:274)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at javax.swing.SwingWorker.run(SwingWorker.java:313)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
"SwingWorker-pool-3-thread-3" prio=6 tid=0x07fd7000 nid=0x11a8 waiting for monitor entry [0x0a2af000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.awt.Component.resize(Component.java:2044)
- waiting to lock <0x24b936a0> (a java.awt.Component$AWTTreeLock)
at java.awt.Component.setSize(Component.java:2035)
at java.awt.Component.resize(Component.java:2069)
at java.awt.Component.setSize(Component.java:2060)
at javax.swing.JViewport.setViewSize(JViewport.java:1038)
at javax.swing.ViewportLayout.layoutContainer(ViewportLayout.java:183)
at java.awt.Container.layout(Container.java:1421)
at java.awt.Container.doLayout(Container.java:1410)
at jsyntaxpane.components.LineNumbersRuler.updateSize(LineNumbersRuler.java:109)
at jsyntaxpane.components.LineNumbersRuler.removeUpdate(LineNumbersRuler.java:203)
at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:243)
at jsyntaxpane.SyntaxDocument.fireRemoveUpdate(SyntaxDocument.java:118)
at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:608)
at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:576)
at javax.swing.JEditorPane.setText(JEditorPane.java:1493)
at sum.ee.ui.SourceCodePanel.clearSourcePane(SourceCodePanel.java:256)
at sum.ee.ui.SourceCodePanel.access$100(SourceCodePanel.java:47)
at sum.ee.ui.SourceCodePanel$1.stateChanged(SourceCodePanel.java:209)
at sum.ee.ui.VisualizationAggregator.fireStateChanged(VisualizationAggregator.java:300)
at sum.ee.ui.VisualizationAggregator.update(VisualizationAggregator.java:97)
at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:918)
at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:877)
at javax.swing.SwingWorker$1.call(SwingWorker.java:274)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at javax.swing.SwingWorker.run(SwingWorker.java:313)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor
$ Worker.run (ThreadPoolExecutor.java:908) à java.lang.Thread.run (Thread.java:619)
Ma compréhension est ce travail GUI ne devrait pas être fait dans doInBackground(), mais plutôt dans done(). J'ai effectué une expérience naïve où j'ai déplacé tout le code dans doInBackground() dans done() et cela ne fonctionnait toujours pas. Y at-il des conseils que les gens peuvent me donner sur ce que je peux faire pour causer ce problème? Le code ressemble à ceci:
protected Void doInBackground() {
isAnimating = true;
resetButtonBackgrounds();
backgroundColor = new Color(175, 255, 175); // Soft Green
JToggleButton b = null;
for (final int index : modelIndices) {
if (index == modelIndices.get(modelIndices.size() - 1)) {
backgroundColor = defaultBackgroundColor;
}
if (!keepTrace) {
// Resetting the backgrounds is necessary to have
// individual display of the changing elements due to
// the fact that there can be multiple nodes per
// source line. The reset works in combination
// with updating from ModelViewer.this (as opposed
// to the 'this' of ModelAnimator instances) due
// to not sending an event to itself. Furthermore,
// if the event was sent from ModelAnimator, the model
// indices are recalculated, causing a jump when multiple
// element source lines are encountered.
resetButtonBackgrounds();
}
aggregator.modelIndex(index);
aggregator.update(ModelViewer.this);
b = getButtonByIndex(index);
scrollRectToVisible(b.getBounds());
ModelViewer.this.repaint();
try {
StaticTools.sleepAtLeast(sleepTimeMilliseconds);
} catch (final InterruptedException ex) {
// continue with thread
}
}
isAnimating = false;
if (b != null) {
Color orig = b.getBackground();
Color blink = Color.PINK;
Color current = orig;
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
if (current == orig) {
current = blink;
} else {
current = orig;
}
b.setBackground(current);
ModelViewer.this.repaint();
}
}
return null;
}
L'autre indice est qu'il ya deux fils de SwingWorker qui exécutent. Peuvent-ils courir le même fil?
MISE À JOUR: Voici le code qui exécute la SwingWorker:
finale Animer public void (delayBetweenUpdatesMilliseconds longue finale, modelIndices Liste finale, keepTrace booléen finale, propertyChangeListeners Liste finale) {
ModelAnimator modelAnimator =
new ModelAnimator(delayBetweenUpdatesMilliseconds, modelIndices,
keepTrace);
for (final PropertyChangeListener listener : propertyChangeListeners) {
modelAnimator.addPropertyChangeListener(listener);
}
modelAnimator.execute();
}
Je ne suis pas un expert, mais on dirait que vous avez un blocage. À quoi ressemble le code qui appelle cette méthode? – ChadNC
Salut Tchad, merci pour la réponse. Je pensais que si j'avais une impasse, la trace de la pile l'aurait montré - c'est généralement ce qu'elle fait. Le code qui appelle cela exécute simplement() sur le SwingWorker. –
Peut être les appels consécutifs à dormir(). Le thread peut encore être en train de dormir lorsque vous faites le second appel pour dormir et cela peut être la raison de l'impasse.J'ai toujours créé une instance de l'objet exécutable pour les threads de travail. – ChadNC