2017-07-09 37 views
0

我有一个Runnable“NanoClock”类不断更新其run()方法私人挥发性双重价值。的Java:volatile变量不更新(get和set方法不工作)

这个类也具有getTime()方法,该方法返回双精度值。另一类(“Master”)正在构造NanoClock类,并创建一个线程,并调用start()方法。

它这样做后,它会调用getTime()方法多次(有延迟),但价值没有更新。我究竟做错了什么?

NanoClock.java:

public class NanoClock implements Runnable { 
    private volatile boolean running; 
    private volatile double time; 
    public NanoClock() { 
     time = System.currentTimeMillis(); 
    } 
    @Override 
    public void run() { 
     running = true; 
     while(running) { 
      try { 
       if(System.currentTimeMillis() > time) { 
        time = System.currentTimeMillis(); 
       } 
       //This returns the updated value continuously when commented out 
       //System.out.println("Time: " + String.format("%.6f", unix_time)); 
       Thread.sleep(2000); 
      } catch(Exception exc) { 
       exc.printStackTrace(); 
       System.exit(1); 
      } 
     } 
    } 
    public double getTime() { 
     return time; 
    } 
    public void end() { 
     running = false; 
    } 
} 

Master.java:

public class Master { 
    public static void main(String[] args) { 
     try { 
      NanoClock nClock = new NanoClock(); 
      Thread clockThread = new Thread(new NanoClock()); 
      clockThread.setPriority(10); 
      clockThread.start(); 
      //MY_ISSUE: This returns the same value every time 
      for(int a = 0; a < 10; a++) { 
       System.out.println("Time: " + nClock.getTime()); 
      } 
      //MY_ISSUE: This cannot stop the while loop - I tested it with 
      //the println in the NanoClock class. 
      nClock.end(); 
      System.out.println("Done!"); 
     catch(Exception e) { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 
} 
+0

你总是在run方法中将运行设置为true,所以你的while循环将永远不会停止... – home

+0

你认为'new NanoClock()'做了什么? –

+0

@home但运行方法只调用一次,对吧?所以它应该将运行转化为true,然后停留在while循环中,直到我将运行的值更改为false,这会导致完成方法并结束线程...或者运行方法是由它自己连续调用的吗? @SotiriosDelimanolis我想'新的NanoClock()'调用类的构造函数并创建objet的实例,然后我可以转换为一个线程。我已经多次见过这种做法......它有什么问题吗? – AlpayY

回答

1

你得的NanoClock 实例:其中之一是匿名new NanoClock()它,在你的其他线程的Runnable是高高兴兴保持时间在背景中;另一个是nClock,它在你的主线程中前台闲置。

nClock应该已经在其他线程Runnable

Thread clockThread = new Thread(nClock); // not new NanoClock() 

这可能不是整个解决方案,但它应该是在正确的方向迈出了一大步。

+0

就是这样,谢谢!有时你只是盲目的...这帮了我很多,非常感谢! – AlpayY

0

System.currentTimeMillis()返回长,但你把它保存在一个双,这会导致精度的损失。当你更改成员时间(以及它的getter的返回类型)为一个很长的时间时,你应该得到预期的结果。

作为一个经验法则:当随时间单位工作时间长是最合适的数据类型的大部分时间。浮点数不适合存储精确的结果。

+0

最初,这行代码做了其他事情。它将时间转换为unixtime格式,所以我需要小数。然而,这并不是问题,在NanoClock中使用println方法时,我得到了正确的结果。我的问题是,run()不会更新易失时间变量。 – AlpayY

+0

@AlpayY这可能是问题的一部分,因为当您将当前时间与您的时间变量进行比较时,会发生隐式投射。我不确定你的状况如你所料。其他人指出,您的代码还存在其他问题。所以我的帖子可能只是你问题的一小部分。 –

0

如果下面的代码需要2秒,那么时间会改变。

//MY_ISSUE: This returns the same value every time 
for(int a = 0; a < 10; a++) { 
    System.out.println("Time: " + nClock.getTime()); 
} 

然而,一个for循环有10次迭代和一个system.out甚至不会花费一毫秒,所以它不会改变。

为什么2秒?因为你的可运行代码中有一个Thread.sleep。

Thread.sleep(2000); 

这意味着,下一次更新将在2秒内完成。

并使用System.nanoTime()代替System.currentTimeMillis的(),因为你真正想要的纳米时间不米利斯。


更新时间:

在我的机器

public static void main(String args[]) { 
    long start = System.currentTimeMillis(); 
    for(int a = 0; a < 10; a++) { 
     System.out.println("Iterating " + a); 
    } 
    long end = System.currentTimeMillis(); 
    System.out.println("Start = " + start); 
    System.out.println("End = " + end); 
} 

结果,有

Iterating 0 
Iterating 1 
Iterating 2 
Iterating 3 
Iterating 4 
Iterating 5 
Iterating 6 
Iterating 7 
Iterating 8 
Iterating 9 
Start = 1499592836298 
End = 1499592836298 

该代码块执行的如此之快,在开始时间和结束时间没有差异它甚至不需要一毫秒。根据时间的不同,可能需要1毫秒。

它更改为System.nanoTime()

public static void main(String args[]) { 
    long start = System.nanoTime(); 
    for(int a = 0; a < 10; a++) { 
     System.out.println("Iterating " + a); 
    } 
    long end = System.nanoTime(); 
    System.out.println("Start = " + start); 
    System.out.println("End = " + end); 
} 

结果是,存在在开始时间和结束时间的差。

Iterating 0 
Iterating 1 
Iterating 2 
Iterating 3 
Iterating 4 
Iterating 5 
Iterating 6 
Iterating 7 
Iterating 8 
Iterating 9 
Start = 1012518090518837 
End = 1012518091012960 
+0

谢谢,当我发布这个问题时,我似乎犯了这个错误......我在NanoClock的run()中删除了睡眠,并在for循环中添加了Thread.sleep(2000)。但我总是得到相同的价值,所以问题仍然存在。 – AlpayY

+0

再次,for循环甚至不会花费一毫秒。 – Itherael

+0

谢谢,可视化非常有用!尽管我的问题在于同时存在的两个NanoClock实例,但这也是我在尝试测试NanoClock类的不同方式时犯的一个错误。 – AlpayY

0
Thread.sleep(2000); 
System.out.println("Time: " + nClock.getTime()); 

formain()必须sleep(2000)

+0

谢谢!对不起,我在我的实际程序中有这个。我现在改变了这一点,我删除了NanoClock类中的睡眠,并在for循环中添加了一个sleep(2000),但我仍然得到相同的double值。每次迭代。 – AlpayY