Files
ebean/src/main/java/com/avaje/ebeaninternal/server/lib/BackgroundThread.java
T

221 lines
4.6 KiB
Java

package com.avaje.ebeaninternal.server.lib;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.Vector;
/**
* A general background thread that runs registered tasks periodically.
* <p>
* Several features such as CacheManager, DataSourceManager, ThreadPoolManager
* require tasks to be undertaken periodically. Instead of each having their own
* background thread they register runnables with this one.
* </p>
* <p>
* SystemProperties:<br>
*
* <pre><code>
* ## initially sleep for 5 seconds before starting
* backgroundthread.initialsleep=5
* </code></pre>
*
* </p>
*
* @see BackgroundRunnable
*/
public final class BackgroundThread {
private static final Logger logger = LoggerFactory.getLogger(BackgroundThread.class);
private static final BackgroundThread me = new BackgroundThread();
/**
* The list of Runnable tasks.
*/
private Vector<BackgroundRunnable> list = new Vector<BackgroundRunnable>();
/**
* Used to synchronize the list.
*/
private final Object monitor = new Object();
/**
* The underlying background thread.
*/
private final Thread thread;
/**
* Wakes every second to look for tasks to run.
*/
private long sleepTime = 1000;
/**
* The number of times a task is run.
*/
private long count;
/**
* The time it takes to run the tasks.
*/
private long exeTime;
/**
* Set when shutting down.
*/
private boolean stopped;
/**
* Used to shutdown nicely.
*/
private Object threadMonitor = new Object();
private BackgroundThread() {
thread = new Thread(new Runner(), "EbeanBackgroundThread");
thread.setDaemon(true);
thread.start();
}
/**
* Register a Runnable to execute every freqInSecs seconds.
*/
public static void add(int freqInSecs, Runnable runnable) {
add(new BackgroundRunnable(runnable, freqInSecs));
}
/**
* Register a Runnable to execute every freqInSecs seconds.
*/
public static void add(BackgroundRunnable backgroundRunnable) {
me.addTask(backgroundRunnable);
}
/**
* Stop the service.
*/
public static void shutdown() {
me.stop();
}
/**
* Return the registered BackgroundRunnable objects.
*/
public static Iterator<BackgroundRunnable> runnables() {
synchronized (me.monitor) {
return me.list.iterator();
}
}
private void addTask(BackgroundRunnable backgroundRunnable) {
synchronized (monitor) {
list.add(backgroundRunnable);
}
}
/**
* Stop the thread nicely. This will wait a maximum of 10 seconds for
* current work to be finished.
*/
private void stop() {
stopped = true;
synchronized (threadMonitor) {
try {
threadMonitor.wait(10000);
} catch (InterruptedException e) {
;
}
}
// thread = null;
}
private class Runner implements Runnable {
/**
* Run the registered tasks periodically.
*/
public void run() {
if (ShutdownManager.isStopping()) {
return;
}
while (!stopped) {
try {
long actualSleep = sleepTime - exeTime;
if (actualSleep < 0) {
actualSleep = sleepTime;
}
Thread.sleep(actualSleep);
synchronized (monitor) {
runJobs();
}
} catch (InterruptedException e) {
logger.error(null, e);
}
}
// Tell Stop() we have shut ourselves down successfully
synchronized (threadMonitor) {
threadMonitor.notifyAll();
}
}
private void runJobs() {
long startTime = System.currentTimeMillis();
// call trim on each cache
Iterator<BackgroundRunnable> it = list.iterator();
while (it.hasNext()) {
BackgroundRunnable bgr = (BackgroundRunnable) it.next();
if (bgr.isActive()) {
int freqInSecs = bgr.getFreqInSecs();
if (count % freqInSecs == 0) {
Runnable runable = bgr.getRunnable();
if (bgr.runNow(startTime)){
bgr.runStart();
if (logger.isTraceEnabled()) {
String msg = count + " BGRunnable running ["
+ runable.getClass().getName() + "]";
logger.trace(msg);
}
runable.run();
bgr.runEnd();
}
}
}
}
exeTime = System.currentTimeMillis() - startTime;
count++;
if (count == 86400) {
// reset count back to zero every day
count = 0;
}
}
}
public String toString() {
synchronized (monitor) {
StringBuffer sb = new StringBuffer();
Iterator<BackgroundRunnable> it = runnables();
while (it.hasNext()) {
BackgroundRunnable bgr = it.next();
sb.append(bgr);
}
return sb.toString();
}
}
}