package codeine.executer;
import org.apache.log4j.Logger;
import codeine.utils.ExceptionUtils;
import codeine.utils.StringUtils;
import codeine.utils.ThreadUtils;
import com.google.common.base.Stopwatch;
public class PeriodicExecuter implements Runnable
{
private final long sleepTimeMilli;
private Task task;
private volatile boolean shouldStop;
private String taskName;
private boolean sleepFirst;
private static final Logger log = Logger.getLogger(PeriodicExecuter.class);
private Object waitForFirstExecutionSync = new Object();
private boolean firstExecutionFinished = false;
public PeriodicExecuter(long sleepTimeMilli, Task task, String taskName) {
super();
this.sleepTimeMilli = sleepTimeMilli;
this.task = task;
this.taskName = taskName;
}
public PeriodicExecuter(long sleepTime, Task task) {
this(sleepTime, task, task.getClass().getSimpleName());
}
@Override
public void run()
{
log.info("started for task " + taskName);
if (sleepFirst) {
log.info("going to sleep first for " + StringUtils.formatTimePeriod(sleepTimeMilli));
ThreadUtils.wait(getSleepObject(), sleepTimeMilli);
}
while (!shouldStop) {
Stopwatch s = Stopwatch.createStarted();
try {
exec();
} catch (Throwable e1) {
log.warn("error executing task " + taskName, e1);
}
s.stop();
if (!firstExecutionFinished) {
firstExecutionFinished = true;
synchronized (waitForFirstExecutionSync) {
waitForFirstExecutionSync.notifyAll();
}
}
log.info("task " + taskName + " took " + s + " ; going to sleep " + StringUtils.formatTimePeriod(sleepTimeMilli));
ThreadUtils.wait(getSleepObject(), sleepTimeMilli);
}
log.info("finished for task " + taskName);
}
public void waitForFirstExecution(int millisToWait) {
synchronized (waitForFirstExecutionSync) {
if (firstExecutionFinished) {
return;
}
try {
waitForFirstExecutionSync.wait(millisToWait);
} catch (InterruptedException e) {
throw ExceptionUtils.asUnchecked(e);
}
}
}
protected Object getSleepObject() {
if (task instanceof NotifiableTask) {
NotifiableTask task1 = (NotifiableTask) task;
return task1.getSleepObject();
}
return new Object();
}
private void exec() {
log.debug("executing " + taskName);
task.run();
}
public void stopWhenPossible() {
shouldStop = true;
}
public void runInThread() {
ThreadUtils.createThread(this, taskName).start();
}
public void runInThreadSleepFirst() {
this.sleepFirst = true;
ThreadUtils.createThread(this, taskName).start();
}
public String name() {
return taskName;
}
}