Java - 保留先前值的线程变量

时间:2015-08-12 18:40:28

标签: java multithreading netbeans concurrency timer

我创建了一个简单的计时器类,除非它的timerStop变量设置为true,否则会从20倒数到零,并在每秒后更新一个GUI数组中的JTextFiled。每次使用计时器时,都会创建一个新的GameTimer并将其传递给新的Thread。

问题: 计时器的第一次运行按预期执行,但后续实例将通过使用前一个计时器的最后一个值(它停止的数字)更新GUI文本字段开始,然后从20开始倒计时。

我已经尝试在代码末尾将变量重置为20并将值打印出来作为测试,并且该变量确实打印了#34; 20"但仍然是GUI更新下一个实例运行时的上一个停止时间。

我正在使用Netbeans IDE 8.0.2

真的很感激有关我的代码的任何建议和提示,谢谢!

public class GameTimer implements Runnable 
{
  private volatile int secondsLeft;
  private MultiTextGUI[] guis;
  private boolean timerStop; 

  public GameTimer(MultiTextGUI[] MTguis)
  {
    secondsLeft = 20;
    guis = MTguis;
    timerStop = false;
  }     

  public void setTimerStop(boolean stop)
  {
    timerStop = stop;
  }        

  @Override
  public void run()
  {
      while (secondsLeft > 0 && !timerStop)
      {
        try
        {
         Thread.sleep(1000);
        }
        catch (Exception e)
        {
         System.out.println("Error: " + e.toString());
        }    
        secondsLeft--;
        System.out.println(secondsLeft); //TEST
        for (MultiTextGUI gui: guis)
        {
          if (secondsLeft > 0)
          {
             if (gui != null)
             {    
               gui.updateTimer(secondsLeft);
             }
          }
          else
          {
             if (gui != null)
             {    
                gui.setTimerOn(false);
             }
          }
        }

      }
      secondsLeft = 20;
      System.out.println(secondsLeft); //TEST
  }
}

主线程:

GameTimer gt = new GameTimer(g);
Thread timerThread = new Thread(gt);
timerThread.start();

//code to show timer in gui
//code for countdownlatch

gt.setTimerStop(true);

2 个答案:

答案 0 :(得分:0)

如果您使用的是Swing组件,则必须使用事件派发线程更新这些组件。在普通线程内更新组件将导致各种问题。

更新Swing组件时必须使用SwingUtilities.invokeLater。

以下代码确保事件派发线程上的execute中包含的语句。这是至关重要的原因是你可能会破坏你的挥杆UI的状态(假设这里使用的是什么)。绘制GUI是单线程的,如果您跳转并更新该单个线程(EDT)之外的组件,那么EDT可能正在您正在更新组件的过程中。腐败是最少​​的问题。

真正阴险的部分是,更新EDT之外的组件将在90%的时间内正常工作。然后当你最不期望它时,会发生一些疯狂的事情。这可能是你的问题与此无关,但在EDT中更新Swing仍然很重要。

有可用的教程。

SwingUtilities.invokeLater(new Runnable()
{                        
    public void run ()
    {
        label.setText("New Value=" + x);
    }
});

答案 1 :(得分:0)

在MultiTextGUI实例中设置更新值之前,您正在休眠一秒钟。如果显示在此1秒周期之前更新,则运行计时器的线程将不会更新显示的值,从而导致显示先前值。不确定是否可以在Thread.sleep(1000)调用之前设置该值并保留所需的行为。