Java 等待系统时间以继续应用程序
我已经编写了一个类,如果当前秒数是5的倍数(即Calender.second%5==0),则继续启动JAVA应用程序 下面给出了类代码,我好奇的是,我这样做对吗?这似乎不是一个优雅的解决方案,像这样阻止执行并一次又一次地获取实例Java 等待系统时间以继续应用程序,java,datetime,calendar,blocking,busy-waiting,Java,Datetime,Calendar,Blocking,Busy Waiting,我已经编写了一个类,如果当前秒数是5的倍数(即Calender.second%5==0),则继续启动JAVA应用程序 下面给出了类代码,我好奇的是,我这样做对吗?这似乎不是一个优雅的解决方案,像这样阻止执行并一次又一次地获取实例 public class Synchronizer{ private static Calendar c; public static void timeInSync(){ do{ c = Calendar.ge
public class Synchronizer{
private static Calendar c;
public static void timeInSync(){
do{
c = Calendar.getInstance();
}
while(c.get(Calendar.SECOND) % 5 != 0);
}
}
在另一个类的构造函数中调用Synchronizer.timeInSync(),并在主方法的开头创建该类的实例。然后应用程序将永远运行,每5秒调用一次TimerTask
是否有更干净的时间同步解决方案
更新:
我想我没有明确说明,但我在这里寻找的是与系统时间同步,而不做繁忙的等待
所以我需要能够
12:19:00
12:19:05
12:19:10
...
正如@ChrisK所建议的,只需直接调用
System.currentTimeMillis()
即可简化
例如:
long time = 0;
do
{
time = System.currentTimeMillis();
} while (time % 5000 != 0);
请注意,您需要将比较值更改为5000,因为时间的表示形式是以毫秒为单位的
此外,像这样直接进行任何比较都可能存在陷阱,因为循环调用取决于处理器可用性等等,所以这样的实现有可能进行一次调用,返回:
`1411482384999`
然后循环中的下一个调用返回
`1411482385001`
这意味着由于硬件可用性,您的条件已被跳过
如果您想使用内置的调度程序,我建议您在这里查看类似问题的答案,正如@ChrisK建议的那样,您可以通过直接调用
System.currentTimeMillis()
来简化
例如:
long time = 0;
do
{
time = System.currentTimeMillis();
} while (time % 5000 != 0);
请注意,您需要将比较值更改为5000,因为时间的表示形式是以毫秒为单位的
此外,像这样直接进行任何比较都可能存在陷阱,因为循环调用取决于处理器可用性等等,所以这样的实现有可能进行一次调用,返回:
`1411482384999`
然后循环中的下一个调用返回
`1411482385001`
这意味着由于硬件可用性,您的条件已被跳过
如果您想使用内置的调度程序,我建议您在这里查看类似问题的答案
System.nanoTime()
而不是
System.currentTimeMillis()
因为它返回测量的经过时间而不是系统时间,所以nanoTime不受系统时间更改的影响
public class Synchronizer
{
public static void timeInSync()
{
long lastNanoTime = System.nanoTime();
long nowTime = System.nanoTime();
while(nowTime/1000000 - lastNanoTime /1000000 < 5000 )
{
nowTime = System.nanoTime();
}
}
}
公共类同步器
{
公共静态void timeInSync()
{
long lastnotime=System.nanoTime();
long nowTime=System.nanoTime();
而(nowTime/1000000-lastNanoTime/1000000<5000)
{
nowTime=System.nanoTime();
}
}
}
您应该使用
System.nanoTime()
而不是
System.currentTimeMillis()
因为它返回测量的经过时间而不是系统时间,所以nanoTime不受系统时间更改的影响
public class Synchronizer
{
public static void timeInSync()
{
long lastNanoTime = System.nanoTime();
long nowTime = System.nanoTime();
while(nowTime/1000000 - lastNanoTime /1000000 < 5000 )
{
nowTime = System.nanoTime();
}
}
}
公共类同步器
{
公共静态void timeInSync()
{
long lastnotime=System.nanoTime();
long nowTime=System.nanoTime();
而(nowTime/1000000-lastNanoTime/1000000<5000)
{
nowTime=System.nanoTime();
}
}
}
您现在拥有的是所谓的忙等待(有时也称为轮询),是的,它在处理器使用和能源使用方面效率低下。只要操作系统允许,代码就会执行,这样做会阻止CPU用于其他工作,或者当没有其他工作时,会阻止CPU打盹,浪费能源(加热CPU,耗尽电池…)
你应该做的是让你的线程进入睡眠状态,直到你想做某事的时间到来。这允许CPU执行其他任务或进入睡眠状态
java.lang.Thread上有一个方法可以做到这一点:Thread.sleep(长毫秒)
(它也有一个表兄接受一个额外的nanos参数,但是VM可能会忽略nanos,并且很少需要这种精度)
所以首先你要确定什么时候需要做一些工作。然后你一直睡到那时。一个简单的实现可能是这样的:
public static void waitUntil(long timestamp) {
long millis = timestamp - System.currentTimeMillis();
// return immediately if time is already in the past
if (millis <= 0)
return;
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
publicstaticvoidwaituntil(长时间戳){
long millis=时间戳-System.currentTimeMillis();
//如果时间已经过去,请立即返回
if(millis您现在拥有的称为忙等待(有时也称为轮询),是的,它在处理器使用和能源使用方面效率低下。只要操作系统允许,代码就会执行,这样做会阻止CPU用于其他工作,或者在没有其他工作时,会阻止CPU打盹,浪费能源(加热CPU,耗尽电池…)
你应该做的是让你的线程进入睡眠状态,直到你想做的事情到来。这允许CPU执行其他任务或进入睡眠状态
java.lang.Thread上有一个方法可以做到这一点:Thread.sleep(长毫秒)
(它也有一个表兄接受一个额外的nanos参数,但是VM可能会忽略nanos,并且很少需要这种精度)
因此,首先确定什么时候需要做一些工作,然后再睡到那个时候。一个简单的实现可能是这样的:
public static void waitUntil(long timestamp) {
long millis = timestamp - System.currentTimeMillis();
// return immediately if time is already in the past
if (millis <= 0)
return;
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
publicstaticvoidwaituntil(长时间戳){
long millis=时间戳-System.currentTimeMillis();
//如果时间已经过去,请立即返回
if(millis第一个要点是,您永远不能使用忙等待。在java中,您可以通过使用Object.wait(timeout)
或Thread.sleep(timeout)
来避免忙等待。后者更适合您的情况,因为您的情况不需要丢失监视器锁
接下来,您可以使用两种方法来