views:

137

answers:

4

I need to create a java function that will only run for 30 minutes, and at the end of the 30 minutes it executes something. But it should also be able to self terminate before the given time if the right conditions are met. I don't want the function to be sleeping as it should be collecting data, so no sleeping threads.

Thanks

+1  A: 

Get the start time with System.currentTimeMillis(), calculate the time when to stop and check the current time every now and then while you're collecting the data you want to collect. Another way would be to decouple the timer and the data collecting, so that each of them could run in their own threads.

For a more specific answer, it would be helpful if you would tell what data you are collecting and how you are collecting it.

Esko Luontola
I'm reading an accelerometer :) and running an algorithm
Angel Grablev
+4  A: 

Use: Timer.schedule( TimerTask, long )

public void someFunctino() {
    // set the timeout    
    // this will stop this function in 30 minutes
    long in30Minutes = 30 * 60 * 1000;
    Timer timer = new Timer();
    timer.schedule( new TimerTask(){
          public void run() {
               if( conditionsAreMet() ) { 
                   System.exit(0);
                }
           }
     },  in30Minutes );

     // do the work... 
      .... work for n time, it would be stoped in 30 minutes at most
      ... code code code
}
OscarRyz
Thats way better, it wont run thousand times :D
Angel Grablev
Cannot make a static reference to the non-static method schedule(TimerTask, long) from the type Timer
Angel Grablev
@Angel: I've been there already ;)
OscarRyz
@Angel: fixed try again
OscarRyz
wouldn't this just run a task 30 minutes later... rather than run it "for" 30 minutes...
Angel Grablev
The `System#exit()` will however kill the entire JVM. Not sure if this is what OP had in mind.
BalusC
@BaluC indeed, a more complex mechanism is needed, but I hope this would give him a good start.
OscarRyz
+1  A: 

Something like this will work:

long startTime = System.currentTimeMillis();
long maxDurationInMilliseconds = 30 * 60 * 1000;

while (System.currentTimeMillis() < startTime + maxDurationInMilliseconds) {
    // carry on running - 30 minutes hasn't elapsed yet

    if (someOtherConditionIsMet) {
        // stop running early
        break;
    }
}
Richard Fearn
Awesome :) thanks so much!
Angel Grablev
Good answer. It can be a good idea to throw in a short Thread.sleep() in every iteration as well unless you want to eat 100% of a CPU
mikera
Minor suggestion: assign `startTime + maxDurationInMilliseconds` to a variable and use that variable in the loop condition. That way the addition won't be performed 1800000 times :)
Anita
@Anita: I would imagine the VM would hoist that calculation out of the condition and calculate it just once. After all, `startTime` and `maxDurationInMilliseconds` are local to the running thread.
Richard Fearn
@mikera: depends on the work that's being done by the method. It might involve a lot of I/O, or might be issuing requests and waiting for a reponse. The question was a bit vague. Of course if the method is simply waiting for (up to) 30 minutes, then yes, it should sleep for a while in each iteration.
Richard Fearn
+1  A: 

The modern java.util.concurrent way would be using ExecutorService. There are several invoke methods taking a timeout.

Here's a kickoff example:

public static void main(String args[]) throws Exception {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.invokeAll(Arrays.asList(new Task()), 30, TimeUnit.MINUTES);
    executor.shutdown();
}

where Task look like this:

public class Task implements Callable<String> {

    @Override
    public String call() {
        // Just a dummy long running task.
        BigInteger i = new BigInteger("0");
        for (long l = 0; l < Long.MAX_VALUE; l++) {
            i.multiply(new BigInteger(String.valueOf(l)));

            // You need to check this regularly..
            if (Thread.interrupted()) {
                System.out.println("Task interrupted!");
                break; // ..and stop the task whenever Thread is interrupted.
            }
        }
        return null; // Or whatever you'd like to use as return value.
    }

}

See also:

BalusC