2009-11-24 9 views
1

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(); 

}

+1

Je ne suis pas un expert, mais on dirait que vous avez un blocage. À quoi ressemble le code qui appelle cette méthode? – ChadNC

+0

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. –

+0

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

Répondre

1

Il s'agit d'un échec d'observation des règles Swing EDT. Le but de SwingWorker est d'effectuer de lourdes tâches non GUI lorsqu'un événement de l'interface utilisateur se produit qui bloquerait l'interface utilisateur, puis de mettre à jour l'interface utilisateur à la fin.

Ainsi, vous devez implémenter votre poids dans doInBackground(); Une fois terminé, swing appelle done() sur l'EDT et vous pouvez récupérer les résultats en utilisant get().

Le problème ici est que vous travaillez sur l'interface graphique dans le nouveau thread créé par SwingWorker. Cela peut entraîner des blocages et des problèmes de concurrence.

Cela inclut la création desdits objets de l'interface graphique, qui devrait être runnables même si votre déjà sur les EDT

actions telles que:

b = getButtonByIndex(index); 

doivent être gainés dans un Runnable avec invokeAndWait. Les trucs qui modifient réellement l'interface graphique lui-même doivent être dans leurs propres exécutables, même si vous êtes déjà dans le fil de l'événement swing en réponse à un bouton appuyer ou modifier, vous courez le risque de travailler sur des objets sur lesquels vous travaillez déjà.

par exemple. swing fonctionne et est verrouillé A pour vous laisser travailler, vous permettant de travailler sur B essayant de verrouiller et de travailler sur A

Questions connexes