简体   繁体   中英

Execute code every second with only the current time?

How can i execute code every second when only using the current time? ( no extra variables , it doesn't have the be exactly every second, I'm quite happy with a variation between 800 to 1200 ms)

I did try:

//code repeated every 30-100ms
if ((System.currentTimeMillis() % 1000) == 0) { //execute code

But this doesn't work, cause the chance that currentTimeMillis can be exactly divided by 1000 is not very high.

Any bright ideas on the subject?

[edit] please note my "no extra variables" remark. Let me explain a bit better: i need to put this code in a place where i only have a long value indicating the unix time since 1970 (the value of currentTimeMillis). I can't remember anything, nor can i save extra variables that can be accessed the next time my code is executed. It's a special case.

The best way to do this is to use ScheduledExecutorService

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
Future future = service.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);

When you no longer need it, you can cancel execution

future.cancel(true);
while(true) {
  //execute your code here
  Thread.sleep(1000);
}

The only way I can think of to do this would be to check that we are in the time window, perform the action and then use Thread.sleep long enough to ensure we are out of the time window.

private static final long WINDOW = 200;

void doItOncePerSecond(long time) throws InterruptedException {
    // Check the time.
    if ((time % 1000) / WINDOW == 0) {
        // Do your work.
        System.out.println("Now!! " + time + " - " + (time % 1000));
        // Wait long enopugh to be out of the window.
        Thread.sleep(WINDOW - (time % 1000));
    }
}

public void test() throws InterruptedException {
    System.out.println("Hello");
    long start = System.currentTimeMillis();
    long t;
    while ((t = System.currentTimeMillis()) - start < 10000) {
        doItOncePerSecond(t);
        Thread.sleep(100);
    }
}

Beyond that you may need to persist a value in some other way - perhaps use a socket to yourself.

This if statement would do it as per you request (between 800ms and 1200ms) but it is very inefficient and my previous answer or some of the other answers would be a lot better at doing what you want

if ((System.currentTimeMillis() % 1000) < 200 || (System.currentTimeMillis() % 1000) > 800) {

}

or since you code is repeated roughly every 30-100 ms you can use

if ((System.currentTimeMillis() % 1000) < 100|| (System.currentTimeMillis() % 1000) > 900) {

}

You can use java.util.Timer for this, but you can't do this scheduled operation without defining extra variable or it will be in infinity mode.

You can try this:

new Timer().schedule(task, delay, period);

You can try this to get seconds and use it the way you would like to ...

long timeMillis = System.currentTimeMillis();
long timeSeconds = TimeUnit.MILLISECONDS.toSeconds(timeMillis);

This does something every 1 second

while (true) {
    System.out.println("a second has passed");
    Thread.sleep(1000);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM