9

I have written the following code:

import java.util.Calendar;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

class Voter {   
public static void main(String[] args) {
    ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(2);
    stpe.scheduleAtFixedRate(new Shoot(), 0, 1, TimeUnit.SECONDS);
}
}

class Shoot implements Runnable {
Calendar deadline;
long endTime,currentTime;

public Shoot() {
    deadline = Calendar.getInstance();
    deadline.set(2011,6,21,12,18,00);
    endTime = deadline.getTime().getTime();
}

public void work() {
    currentTime = System.currentTimeMillis();

    if (currentTime >= endTime) {
        System.out.println("Got it!");
        func();
    } 
}

public void run() {
    work();
}

public void func() {
    // function called when time matches
}
}

I would like to stop the ScheduledThreadPoolExecutor when the func() is called. There is no need for it to work futher! I think i should put the function func() inside Voter class, and than create some kind of callback. But maybe I can do it from within the Shoot class.

How can I solve it properly?

Khozzy
  • 1,064
  • 4
  • 15
  • 29
  • I'm not all that familiar with `ScheduledThreadPoolExecutor`, but my first guess would be `stpe.shutdown()`. You do need to make `stpe` reachable from `func()` for that. It might be reasonable to start a second thread (scheduled?) that runs at the deadline time and calls the `shutdown()` function. – Dorus Jul 21 '11 at 11:01

1 Answers1

21

The ScheduledThreadPoolExecutor allows you to execute your task right away or schedule it to be executed later (you can set periodical executions also).

So, if you will use this class to stop your task execution keep in mind this:

  1. There is no way to guarantee that one thread will stop his execution. Check the Thread.interrupt() documentation.
  2. The method ScheduledThreadPoolExecutor.shutdown() will set as canceled your task, and it will not try to interrupt your threads. With this method you actually avoid the execution of newer tasks, and the execution of scheduled but not started tasks.
  3. The method ScheduledThreadPoolExecutor.shutdownNow() will interrupt the threads, but as I said in the first point of this list ...

When you want to stop the scheduler you must do something like this:

    //Cancel scheduled but not started task, and avoid new ones
    myScheduler.shutdown();

    //Wait for the running tasks 
    myScheduler.awaitTermination(30, TimeUnit.SECONDS);

    //Interrupt the threads and shutdown the scheduler
    myScheduler.shutdownNow();

But what if you need to stop only one task?

The method ScheduledThreadPoolExecutor.schedule(...) returns a ScheduleFuture that is a representation of your already scheduled task. So, you can call the ScheduleFuture.cancel(boolean mayInterruptIfRunning) method to cancel your task and try to interrupt it if you need to.

ggarciao
  • 1,618
  • 16
  • 29
  • 7
    I need just one clarification on the above: Why can't we just do myScheduler.shutdownNow() ? What my concern is awaiting termination for a task to complete may take any arbitrary time. So why go for the first two lines? – abksrv Apr 01 '15 at 05:27