倒数计时器 - 从变量读取错误

时间:2015-08-18 06:28:04

标签: java multithreading swing concurrency thread-safety

我创建了一个简单的GameTimer类,它从给定的数字倒计时,一个包含updateTimer()方法的Swing GUI,它更新EDT上的计时器组件,以及一个RunTimer类,它连续调用updateTimer()直到GameTimer停止

计时器的第一个实例总是正常运行,但一旦停止并创建并启动另一个计时器,新计时器有时会在当前倒计时和最后一个计时器停止的值之间闪烁。

将组件更新移至EDT似乎无效。

在计时器的最后一次旋转之后调用updateTimer()以确保更新最后一个值还没有工作。

制作' secondsLeft'变量静态解决了问题,但这意味着我无法同时使用GameTimer的多个实例来计时不同的事件。

我添加了输出,当我从20开始倒数​​计时器时打印出变量值,将其停在17,然后创建并启动一个新的倒数计时器。

困惑,请帮忙!

  public class GameTimer implements Runnable {

    private int secondsLeft; 
    private boolean timerStop; 
    /**
    * Creates a timer with a given number of seconds on the clock.
    */
    public GameTimer(int seconds)
    {     
    secondsLeft = seconds;
    timerStop = false; // Set to true when timer should stop
    }

    /**
    * Stops timer permanently 
    */
    public void stopTimer()
    {
     timerStop = true;
    }

    public int getSecondsLeft()
    {
     return secondsLeft;   
    }         

    @Override
    public void run()
    {
     // While there timer is still counting down or all players finish 
     // their actions.
      while (!timerStop)
      {
        //TEST  
        System.out.println("GamerTimer before sleep reads: " +             String.valueOf(secondsLeft));  

        // Wait 1 second  
        try
        {
         Thread.sleep(1000);
        }
        catch (Exception e)
        {
         System.out.println("Error: " + e.toString());
        }  

        //decrement timer 1 second
        secondsLeft--;

        if (secondsLeft <= 0)
        {
          timerStop = true;
        }    

        //TEST - COMMENT OUT AFTER TESTING
        System.out.println("GamerTimer after sleep reads: " + String.valueOf(secondsLeft));
      }     
    }
}



    private void updateTimer(final int secondsLeft)
    {
      timePanel.setVisible(true);

      try
      {     
         SwingUtilities.invokeLater(new Runnable(){      

         @Override
         public void run() 
         {    
            //TEST VALUES - COMMENT OUT AFTER TESTING   
            //System.out.println(String.valueOf(SwingUtilities.isEventDispatchThread()));
            timeTextField.setText(String.valueOf(secondsLeft));

            if (secondsLeft <= 5)
            {
              timeTextField.setBackground(Color.yellow);
            }
            else
            {   
              timeTextField.setBackground(Color.white);
            }
           }
         });
      }
      catch (Exception e)
      {
        System.out.println("Error: " + e.toString());   
      }    
    }    




     public class RunTimer implements Runnable
    {  

     private GameTimer t;    

     public RunTimer(final GameTimer timer)
     {
       t = timer;  
     }        

     @Override
     public void run()
     {      
       stopTimer = false;

       while (!stopTimer)
       {    
         //TEST VALUES - COMMENT OUT AFTER TESTING  
         System.out.println("RunTimer class reads: " + String.valueOf(t.getSecondsLeft()));

         updateTimer(t.getSecondsLeft());
         try
         {
          Thread.sleep(500);
         }
         catch (Exception e)
         {
          System.out.println("Error: " + e.toString());
         }
       }

       timePanel.setVisible(false);
     }
    }



    **Output Results:**
    GamerTimer before sleep reads: 20
    RunTimer class reads: 20
    RunTimer class reads: 20
    GamerTimer after sleep reads: 19
    GamerTimer before sleep reads: 19
    RunTimer class reads: 19
    RunTimer class reads: 19
    GamerTimer after sleep reads: 18
    GamerTimer before sleep reads: 18
    RunTimer class reads: 18
    RunTimer class reads: 18
    GamerTimer after sleep reads: 17
    GamerTimer before sleep reads: 17
    RunTimer class reads: 17
    GamerTimer before sleep reads: 20
    RunTimer class reads: 20
    RunTimer class reads: 17
    RunTimer class reads: 20
    GamerTimer after sleep reads: 16
    RunTimer class reads: 16
    GamerTimer after sleep reads: 19
    GamerTimer before sleep reads: 19
    RunTimer class reads: 19
    RunTimer class reads: 16
    RunTimer class reads: 19
    RunTimer class reads: 16
    GamerTimer after sleep reads: 18
    GamerTimer before sleep reads: 18
    RunTimer class reads: 18
    RunTimer class reads: 16
    RunTimer class reads: 18
    RunTimer class reads: 16
    GamerTimer after sleep reads: 17
    GamerTimer before sleep reads: 17
    RunTimer class reads: 17
    RunTimer class reads: 16
    RunTimer class reads: 17
    RunTimer class reads: 16
    BUILD STOPPED (total time: 11 seconds)

0 个答案:

没有答案