Modified ThreadService & Scheduler to allow the web server to pass a delegate service such that all webapps will use one service for each function (reduction in threading and debug complexity).
This commit is contained in:
@@ -10,21 +10,44 @@ package com.common.thread;
|
|||||||
import com.common.util.*;
|
import com.common.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Warning: This is a long running scheduler with large granularity (30 seconds). If you want a small grained scheduler that is semi-real-time, look at ActiveScheduler.</p>
|
|
||||||
* This class will allow one thread to kick off tasks at regular intervals.
|
* This class will allow one thread to kick off tasks at regular intervals.
|
||||||
* The intent is for the task interval to be greater than a second and to take no more than several milliseconds to process. A task may kick off a thread if more time is required.
|
* The intent is for the task interval to be greater than a second and to take no more than several milliseconds to process. A task may kick off a thread if more time is required.
|
||||||
* The benifit of this Scheduler is that one thread can be used to perform many tasks at regular intervals. This saves resources and improves execution speed.
|
* The benefit of this Scheduler is that one thread can be used to perform many tasks at regular intervals. This saves resources and improves execution speed.
|
||||||
|
* @warning This is a long running scheduler with large granularity (30 seconds). If you want a small grained scheduler that is semi-real-time, look at ActiveScheduler.
|
||||||
|
* @todo It would be nice to use Inversion of Control (IoC) or Dependancy Injection (DI) to handle the delegate functionality, but it is not going to be done at this time since that seems to open up possible incompatibilities and adds complexity at this time.
|
||||||
*/
|
*/
|
||||||
public class Scheduler {
|
public class Scheduler {
|
||||||
private static Scheduler singleton = new Scheduler();
|
private static Scheduler singleton = new Scheduler();
|
||||||
|
private static ISchedulerDelegate delegate = null;
|
||||||
private LiteList scheduledTasks; //Contains handlers for removing old messages from newsgroups.//
|
private LiteList scheduledTasks; //Contains handlers for removing old messages from newsgroups.//
|
||||||
private ScheduleRunnable scheduleRunnable;
|
private ScheduleRunnable scheduleRunnable;
|
||||||
private volatile boolean isRunning = true; //Will start out running as we don't have a startup method.//
|
private volatile boolean isRunning = true; //Will start out running as we don't have a startup method.//
|
||||||
|
|
||||||
|
public interface ISchedulerDelegate {
|
||||||
|
/**
|
||||||
|
* Adds a task to be executed at regular intervals.
|
||||||
|
* @param intervalTime long The amount of time in milliseconds between handler calls. How accurate the scheduler is depends on its' interval time.
|
||||||
|
* @param taskHandler Task The handler to be called at <code>intervalTime</code> intervals. If the handler takes more than a few milliseconds to complete it should start a thread of execution.
|
||||||
|
* @param runImmediatly boolean A flag that lets the scheduler know that the task should be run for the first time as soon as possible.
|
||||||
|
* @return A task reference that should be used to remove the task handler from the scheduled task list.
|
||||||
|
*/
|
||||||
|
public Object addTask(long intervalTime, Runnable taskHandler, boolean runImmediatly);
|
||||||
|
/**
|
||||||
|
* Removes a task handler so that the task will no longer be scheduled to execute.
|
||||||
|
* @param task The task to remove.
|
||||||
|
*/
|
||||||
|
public void removeTask(Object task);
|
||||||
|
/**
|
||||||
|
* Gets the running status of the scheduler.
|
||||||
|
* @return True if the scheduler is running.
|
||||||
|
*/
|
||||||
|
public boolean isRunning();
|
||||||
|
}//ISchedulerDelegate//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to be extended and passed as a task that should be run at regular intervals.
|
* A class to be extended and passed as a task that should be run at regular intervals.
|
||||||
*/
|
*/
|
||||||
public static abstract class Task {
|
public static abstract class Task implements Runnable {
|
||||||
Object value = null; //May be used for anything.//
|
Object value = null; //May be used for anything.//
|
||||||
Object taskReference = null;
|
Object taskReference = null;
|
||||||
|
|
||||||
@@ -42,7 +65,6 @@ public class Scheduler {
|
|||||||
private void setTaskReference(Object taskReference) {
|
private void setTaskReference(Object taskReference) {
|
||||||
this.taskReference = taskReference;
|
this.taskReference = taskReference;
|
||||||
}//setTaskReference()//
|
}//setTaskReference()//
|
||||||
public abstract void evaluate();
|
|
||||||
}//Task//
|
}//Task//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +94,7 @@ public class Scheduler {
|
|||||||
//Run the task if it is time.//
|
//Run the task if it is time.//
|
||||||
if(currentTime - lastNotificationTime > intervalTime) {
|
if(currentTime - lastNotificationTime > intervalTime) {
|
||||||
lastNotificationTime = currentTime;
|
lastNotificationTime = currentTime;
|
||||||
taskHandler.evaluate();
|
taskHandler.run();
|
||||||
result = true;
|
result = true;
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
@@ -200,12 +222,28 @@ private void _shutdown() {
|
|||||||
}).start();
|
}).start();
|
||||||
}//_shutdown()//
|
}//_shutdown()//
|
||||||
/**
|
/**
|
||||||
* @see #addTask(long, Task, boolean)
|
* Returns the one and only Scheduler object.
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
public static synchronized Object addScheduledTask(long intervalTime, Task taskHandler, boolean runImmediatly) {
|
private static Scheduler getSingleton() {
|
||||||
return addTask(intervalTime, taskHandler, runImmediatly);
|
return singleton;
|
||||||
}//addScheduledTask()//
|
}//getSingleton()//
|
||||||
|
/**
|
||||||
|
* Sets a delegate for this scheduler. All scheduled tasks will be given to the delegate to handle. This cannot be undone, and must be called prior to using the scheduler.
|
||||||
|
* @warning This method should be called at the very beginning of any application to ensure proper functioning since multi threaded access to the class prior to calling this method will cause problems. This code does not enforce proper behavior or detect errors due to the complexity and cost of doing so.
|
||||||
|
* @param _delegate The non-null delegate.
|
||||||
|
*/
|
||||||
|
public static void setDelegate(ISchedulerDelegate _delegate) {
|
||||||
|
synchronized(singleton) {
|
||||||
|
if(delegate == null && _delegate != null && getSingleton().scheduledTasks.getSize() == 0) {
|
||||||
|
delegate = _delegate;
|
||||||
|
//Shutdown this scheduler so the delegate takes over.//
|
||||||
|
getSingleton().shutdown();
|
||||||
|
}//if//
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Must set the scheduler delegate prior to the scheduler being used.");
|
||||||
|
}//else//
|
||||||
|
}//synchronized//
|
||||||
|
}//setDelegate()//
|
||||||
/**
|
/**
|
||||||
* Adds a task to be executed at regular intervals.
|
* Adds a task to be executed at regular intervals.
|
||||||
* @param intervalTime long The amount of time in milliseconds between handler calls. How accurate the scheduler is depends on its' interval time.
|
* @param intervalTime long The amount of time in milliseconds between handler calls. How accurate the scheduler is depends on its' interval time.
|
||||||
@@ -216,75 +254,65 @@ public static synchronized Object addScheduledTask(long intervalTime, Task taskH
|
|||||||
public static synchronized Object addTask(long intervalTime, Task taskHandler, boolean runImmediatly) {
|
public static synchronized Object addTask(long intervalTime, Task taskHandler, boolean runImmediatly) {
|
||||||
Object result = null;
|
Object result = null;
|
||||||
|
|
||||||
if(isRunning()) {
|
if(delegate != null) {
|
||||||
result = getSingleton()._addScheduledTask(intervalTime, taskHandler, runImmediatly);
|
result = delegate.addTask(intervalTime, taskHandler, runImmediatly);
|
||||||
|
taskHandler.setTaskReference(result);
|
||||||
}//if//
|
}//if//
|
||||||
|
else {
|
||||||
|
if(isRunning()) {
|
||||||
|
result = getSingleton()._addScheduledTask(intervalTime, taskHandler, runImmediatly);
|
||||||
|
}//if//
|
||||||
|
}//else//
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}//addTask()//
|
}//addTask()//
|
||||||
/**
|
/**
|
||||||
* Returns the one and only Scheduler object.
|
* Gets the running status of the scheduler.
|
||||||
*/
|
* @return True if the scheduler is running.
|
||||||
private static Scheduler getSingleton() {
|
|
||||||
return singleton;
|
|
||||||
}//getSingleton()//
|
|
||||||
/**
|
|
||||||
* Will return the running status of the scheduler.
|
|
||||||
* @return boolean Will return true if the scheduler is running.
|
|
||||||
*/
|
*/
|
||||||
public static boolean isRunning() {
|
public static boolean isRunning() {
|
||||||
return getSingleton()._isRunning();
|
return delegate != null ? delegate.isRunning() : getSingleton()._isRunning();
|
||||||
}//isRunning()//
|
}//isRunning()//
|
||||||
/**
|
|
||||||
* @see #removeTask(Task)
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public static synchronized void removeScheduledTask(Task task) {
|
|
||||||
if(isRunning()) {
|
|
||||||
getSingleton()._removeScheduledTask(task.getTaskReference());
|
|
||||||
}//if//
|
|
||||||
}//removeScheduledTask()//
|
|
||||||
/**
|
|
||||||
* @see #removeTask(Object)
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public static synchronized void removeScheduledTask(Object taskReference) {
|
|
||||||
if(isRunning()) {
|
|
||||||
getSingleton()._removeScheduledTask(taskReference);
|
|
||||||
}//if//
|
|
||||||
}//removeScheduledTask()//
|
|
||||||
/**
|
/**
|
||||||
* Removes a task handler so that the task will no longer be scheduled to execute.
|
* Removes a task handler so that the task will no longer be scheduled to execute.
|
||||||
* @param task The task to remove.
|
* @param task The task to remove.
|
||||||
*/
|
*/
|
||||||
public static synchronized void removeTask(Task task) {
|
public static synchronized void removeTask(Task task) {
|
||||||
if(isRunning() && task != null) {
|
if(delegate != null) delegate.removeTask(task.getTaskReference());
|
||||||
getSingleton()._removeScheduledTask(task.getTaskReference());
|
else {
|
||||||
}//if//
|
if(isRunning() && task != null) {
|
||||||
|
getSingleton()._removeScheduledTask(task.getTaskReference());
|
||||||
|
}//if//
|
||||||
|
}//else//
|
||||||
}//removeTask()//
|
}//removeTask()//
|
||||||
/**
|
/**
|
||||||
* Removes a task handler so that the task will no longer be scheduled to execute.
|
* Removes a task handler so that the task will no longer be scheduled to execute.
|
||||||
* @param taskReference The reference to the task to be removed.
|
* @param taskReference The reference to the task to be removed.
|
||||||
*/
|
*/
|
||||||
public static synchronized void removeTask(Object taskReference) {
|
public static synchronized void removeTask(Object taskReference) {
|
||||||
if(isRunning() && taskReference != null) {
|
if(delegate != null) delegate.removeTask(taskReference);
|
||||||
getSingleton()._removeScheduledTask(taskReference instanceof Task ? ((Task) taskReference).getTaskReference() : taskReference);
|
else {
|
||||||
}//if//
|
if(isRunning() && taskReference != null) {
|
||||||
|
getSingleton()._removeScheduledTask(taskReference instanceof Task ? ((Task) taskReference).getTaskReference() : taskReference);
|
||||||
|
}//if//
|
||||||
|
}//else//
|
||||||
}//removeTask()//
|
}//removeTask()//
|
||||||
/**
|
/**
|
||||||
* Will stop the scheduler.
|
* Will stop the scheduler.
|
||||||
*/
|
*/
|
||||||
public static void shutdown() {
|
public static void shutdown() {
|
||||||
boolean canShutdown = false;
|
if(delegate == null) {
|
||||||
|
boolean canShutdown = false;
|
||||||
|
|
||||||
|
synchronized(Scheduler.class) {
|
||||||
|
if((singleton != null) && (isRunning())) {
|
||||||
|
canShutdown = true;
|
||||||
|
}//if//
|
||||||
|
}//synchronized//
|
||||||
|
|
||||||
synchronized(Scheduler.class) {
|
if(canShutdown) {
|
||||||
if((singleton != null) && (isRunning())) {
|
singleton._shutdown();
|
||||||
canShutdown = true;
|
|
||||||
}//if//
|
}//if//
|
||||||
}//synchronized//
|
|
||||||
|
|
||||||
if(canShutdown) {
|
|
||||||
singleton._shutdown();
|
|
||||||
}//if//
|
}//if//
|
||||||
}//shutdown()//
|
}//shutdown()//
|
||||||
}//Scheduler//
|
}//Scheduler//
|
||||||
@@ -14,10 +14,13 @@ import com.common.exception.*;
|
|||||||
/**
|
/**
|
||||||
* This class supports an application by providing a reuse model for threading.
|
* This class supports an application by providing a reuse model for threading.
|
||||||
* By reusing threads, you will speed up an application because the number of outstanding threads can be controlled, and resources can be reused which reduces resource initialization time and garbage collection time.
|
* By reusing threads, you will speed up an application because the number of outstanding threads can be controlled, and resources can be reused which reduces resource initialization time and garbage collection time.
|
||||||
|
* @warning An application's first call to this class shouldn't be within a synchronization block (directly or indirectly) since the lock will be held indefinately by the thread service's thread creator thread (which is how we create clean new threads).
|
||||||
|
* @todo It would be nice to use Inversion of Control (IoC) or Dependancy Injection (DI) to handle the delegate functionality, but it is not going to be done at this time since that seems to open up possible incompatibilities and adds complexity at this time.
|
||||||
*/
|
*/
|
||||||
public class ThreadService {
|
public class ThreadService {
|
||||||
public static final int DEFAULT_PRIORITY = Thread.NORM_PRIORITY;
|
public static final int DEFAULT_PRIORITY = Thread.NORM_PRIORITY;
|
||||||
private static ThreadService singleton = new ThreadService();
|
private static ThreadService singleton = new ThreadService();
|
||||||
|
private static IThreadServiceDelegate delegate = null;
|
||||||
|
|
||||||
private LiteList threadPool = null; //A collection of threads that can be reused.//
|
private LiteList threadPool = null; //A collection of threads that can be reused.//
|
||||||
private int maxThreadPoolSize = 10; //The number of threads that may be waiting to be reused.//
|
private int maxThreadPoolSize = 10; //The number of threads that may be waiting to be reused.//
|
||||||
@@ -30,6 +33,44 @@ public class ThreadService {
|
|||||||
|
|
||||||
/** A thread local to be used with non-reusable threads to determine whether they are marked as accessing data in a single threaded manner. */
|
/** A thread local to be used with non-reusable threads to determine whether they are marked as accessing data in a single threaded manner. */
|
||||||
private static final ThreadLocal isInSingleThreadedContext = new ThreadLocal();
|
private static final ThreadLocal isInSingleThreadedContext = new ThreadLocal();
|
||||||
|
|
||||||
|
public interface IThreadServiceDelegate {
|
||||||
|
/**
|
||||||
|
* Gets the status of the thread service.
|
||||||
|
* @return True if the thread service is running.
|
||||||
|
*/
|
||||||
|
public boolean isRunning();
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
*/
|
||||||
|
public void run(Runnable target);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param priority The thread priority.
|
||||||
|
*/
|
||||||
|
public void run(Runnable target, int priority);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param queueable Whether the thread request can be queued if there are not threads immediatly available. If the thread request is queued then the return value will be null.
|
||||||
|
* @return The reference to the thread executing the target, or null if the target was queued until a thread becomes available.
|
||||||
|
*/
|
||||||
|
public Thread run(Runnable target, boolean queueable);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param priority The thread priority.
|
||||||
|
* @param queueable Whether the thread request can be queued if there are not threads immediatly available. If the thread request is queued then the return value will be null.
|
||||||
|
* @return The reference to the thread executing the target, or null if the target was queued until a thread becomes available.
|
||||||
|
*/
|
||||||
|
public Thread run(Runnable target, int priority, boolean queueable);
|
||||||
|
}//IThreadServiceDelegate//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A runnable that other threads can block on until the runnable has completed, and that captures the result value of the run.
|
* A runnable that other threads can block on until the runnable has completed, and that captures the result value of the run.
|
||||||
@@ -328,9 +369,26 @@ private int getMaxThreadPoolSize() {
|
|||||||
* This method returns that one instance.
|
* This method returns that one instance.
|
||||||
* @return ThreadService The one and only ThreadService instance.
|
* @return ThreadService The one and only ThreadService instance.
|
||||||
*/
|
*/
|
||||||
public static ThreadService getSingleton() {
|
private static ThreadService getSingleton() {
|
||||||
return singleton;
|
return singleton;
|
||||||
}//getSingleton()//
|
}//getSingleton()//
|
||||||
|
/**
|
||||||
|
* Sets a delegate for this thread service. All runnables will be given to the delegate to handle. This cannot be undone, and must be called prior to using the thread service.
|
||||||
|
* @warning This method should be called at the very beginning of any application to ensure proper functioning since multi threaded access to the class prior to calling this method will cause problems. This code does not enforce proper behavior or detect errors due to the complexity and cost of doing so.
|
||||||
|
* @param _delegate The non-null delegate.
|
||||||
|
*/
|
||||||
|
public static void setDelegate(IThreadServiceDelegate _delegate) {
|
||||||
|
synchronized(singleton) {
|
||||||
|
if(delegate == null && _delegate != null && getSingleton().getThreadPool().getSize() == 0) {
|
||||||
|
delegate = _delegate;
|
||||||
|
//Shutdown this scheduler so the delegate takes over.//
|
||||||
|
getSingleton()._shutdown();
|
||||||
|
}//if//
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Must set the thread service delegate prior to the thread service being used.");
|
||||||
|
}//else//
|
||||||
|
}//synchronized//
|
||||||
|
}//setDelegate()//
|
||||||
/**
|
/**
|
||||||
* A listing of all threads created by this thread service (minus the thread that die of course).
|
* A listing of all threads created by this thread service (minus the thread that die of course).
|
||||||
*/
|
*/
|
||||||
@@ -390,11 +448,11 @@ private synchronized Thread internalRun(Runnable target, int priority, boolean q
|
|||||||
return result;
|
return result;
|
||||||
}//run()//
|
}//run()//
|
||||||
/**
|
/**
|
||||||
* Will return the status of the thread service.
|
* Gets the status of the thread service.
|
||||||
* @return boolean Will return true if the thread service is running.
|
* @return True if the thread service is running.
|
||||||
*/
|
*/
|
||||||
public static boolean isRunning() {
|
public static boolean isRunning() {
|
||||||
return getSingleton()._isRunning();
|
return delegate != null ? delegate.isRunning() : getSingleton()._isRunning();
|
||||||
}//isRunning()//
|
}//isRunning()//
|
||||||
/**
|
/**
|
||||||
* Will return a thread to the pool.
|
* Will return a thread to the pool.
|
||||||
@@ -439,7 +497,8 @@ public static void run(Runnable target) {
|
|||||||
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
ThreadService.getSingleton().internalRun(target, DEFAULT_PRIORITY, true);
|
if(delegate != null) delegate.run(target);
|
||||||
|
else ThreadService.getSingleton().internalRun(target, DEFAULT_PRIORITY, true);
|
||||||
}//run()//
|
}//run()//
|
||||||
/**
|
/**
|
||||||
* Runs the target within a thread that can be reused.
|
* Runs the target within a thread that can be reused.
|
||||||
@@ -452,7 +511,8 @@ public static void run(Runnable target, int priority) {
|
|||||||
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
ThreadService.getSingleton().internalRun(target, priority, true);
|
if(delegate != null) delegate.run(target, priority);
|
||||||
|
else ThreadService.getSingleton().internalRun(target, priority, true);
|
||||||
}//run()//
|
}//run()//
|
||||||
/**
|
/**
|
||||||
* Runs the target within a thread that can be reused.
|
* Runs the target within a thread that can be reused.
|
||||||
@@ -467,7 +527,8 @@ public static Thread run(Runnable target, int priority, boolean queueable) {
|
|||||||
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
return ThreadService.getSingleton().internalRun(target, priority, queueable);
|
if(delegate != null) return delegate.run(target, priority, queueable);
|
||||||
|
else return ThreadService.getSingleton().internalRun(target, priority, queueable);
|
||||||
}//run()//
|
}//run()//
|
||||||
/**
|
/**
|
||||||
* Runs the target within a thread that can be reused.
|
* Runs the target within a thread that can be reused.
|
||||||
@@ -481,13 +542,14 @@ public static Thread run(Runnable target, boolean queueable) {
|
|||||||
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
Debug.log("Failed to pass a valid target.", new RuntimeException());
|
||||||
}//if//
|
}//if//
|
||||||
|
|
||||||
return ThreadService.getSingleton().internalRun(target, DEFAULT_PRIORITY, queueable);
|
if(delegate != null) return delegate.run(target, queueable);
|
||||||
|
else return ThreadService.getSingleton().internalRun(target, DEFAULT_PRIORITY, queueable);
|
||||||
}//run()//
|
}//run()//
|
||||||
/**
|
/**
|
||||||
* Shuts down the thread service prior to the application terminating.
|
* Shuts down the thread service prior to the application terminating.
|
||||||
*/
|
*/
|
||||||
public static void shutdown() {
|
public static void shutdown() {
|
||||||
if(singleton != null) {
|
if(singleton != null && delegate == null) {
|
||||||
//Delay the shutdown long enough to allow everything else to shutdown. This is a bit of a cheat, but makes the shutdown process far less complex.//
|
//Delay the shutdown long enough to allow everything else to shutdown. This is a bit of a cheat, but makes the shutdown process far less complex.//
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.foundation.web;
|
||||||
|
|
||||||
|
import com.common.thread.Scheduler.ISchedulerDelegate;
|
||||||
|
import com.foundation.web.interfaces.IScheduler;
|
||||||
|
|
||||||
|
public class SchedulerDelegate implements ISchedulerDelegate {
|
||||||
|
private IScheduler scheduler;
|
||||||
|
public SchedulerDelegate(IScheduler scheduler) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
}//SchedulerDelegate()//
|
||||||
|
public Object addTask(long intervalTime, Runnable taskHandler, boolean runImmediatly) {
|
||||||
|
return scheduler.addTask(intervalTime, taskHandler, runImmediatly);
|
||||||
|
}//addTask()//
|
||||||
|
public void removeTask(Object task) {
|
||||||
|
scheduler.removeTask(task);
|
||||||
|
}//removeTask()//
|
||||||
|
public boolean isRunning() {
|
||||||
|
return scheduler.isRunning();
|
||||||
|
}//isRunning()//
|
||||||
|
}//SchedulerDelegate//
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.foundation.web;
|
||||||
|
|
||||||
|
import com.common.thread.ThreadService.IThreadServiceDelegate;
|
||||||
|
import com.foundation.web.interfaces.IThreadService;
|
||||||
|
|
||||||
|
public class ThreadServiceDelegate implements IThreadServiceDelegate {
|
||||||
|
private IThreadService threadService;
|
||||||
|
public ThreadServiceDelegate(IThreadService threadService) {
|
||||||
|
this.threadService = threadService;
|
||||||
|
}//ThreadServiceDelegate()//
|
||||||
|
public boolean isRunning() {
|
||||||
|
return threadService.isRunning();
|
||||||
|
}//isRunning()//
|
||||||
|
public void run(Runnable target) {
|
||||||
|
threadService.run(target);
|
||||||
|
}//run()//
|
||||||
|
public void run(Runnable target, int priority) {
|
||||||
|
threadService.run(target, priority);
|
||||||
|
}//run()//
|
||||||
|
public Thread run(Runnable target, boolean queueable) {
|
||||||
|
threadService.run(target, queueable);
|
||||||
|
return null;
|
||||||
|
}//run()//
|
||||||
|
public Thread run(Runnable target, int priority, boolean queueable) {
|
||||||
|
threadService.run(target, priority, queueable);
|
||||||
|
return null;
|
||||||
|
}//run()//
|
||||||
|
}//ThreadServiceDelegate//
|
||||||
@@ -207,7 +207,7 @@ public class WebApplication implements IWebApplication, IWebServerApplicationDef
|
|||||||
|
|
||||||
//Start the cycle of creating new keys at a regular interval.//
|
//Start the cycle of creating new keys at a regular interval.//
|
||||||
Scheduler.addTask(keyInterval, new Scheduler.Task() {
|
Scheduler.addTask(keyInterval, new Scheduler.Task() {
|
||||||
public void evaluate() {
|
public void run() {
|
||||||
cycleKeys();
|
cycleKeys();
|
||||||
}//evaluate()//
|
}//evaluate()//
|
||||||
}, false);
|
}, false);
|
||||||
@@ -450,7 +450,7 @@ public WebApplication(String name, WebOptions options, Application application)
|
|||||||
|
|
||||||
//Setup the task to check for stale sessions.//
|
//Setup the task to check for stale sessions.//
|
||||||
Scheduler.addTask(options.getSessionCheckInterval(), new Scheduler.Task() {
|
Scheduler.addTask(options.getSessionCheckInterval(), new Scheduler.Task() {
|
||||||
public void evaluate() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
LiteList removed = new LiteList(10, 100);
|
LiteList removed = new LiteList(10, 100);
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.foundation.web.application;
|
||||||
|
|
||||||
|
import com.common.thread.Scheduler;
|
||||||
|
import com.foundation.web.interfaces.IScheduler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrappers the web server's framework scheduler such that all webapps can use the same scheduler.
|
||||||
|
*/
|
||||||
|
public class SchedulerWrapper implements IScheduler {
|
||||||
|
public SchedulerWrapper() {
|
||||||
|
}//SchedulerWrapper()//
|
||||||
|
public Object addTask(long intervalTime, final Runnable taskHandler, boolean runImmediatly) {
|
||||||
|
return Scheduler.addTask(intervalTime, new Scheduler.Task() {
|
||||||
|
public void run() {
|
||||||
|
taskHandler.run();
|
||||||
|
}//run()//
|
||||||
|
}, runImmediatly);
|
||||||
|
}//addTask()//
|
||||||
|
public void removeTask(Object task) {
|
||||||
|
Scheduler.removeTask(task);
|
||||||
|
}//removeTask()//
|
||||||
|
public boolean isRunning() {
|
||||||
|
return Scheduler.isRunning();
|
||||||
|
}//isRunning()//
|
||||||
|
}//SchedulerWrapper//
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.foundation.web.application;
|
||||||
|
|
||||||
|
import com.common.thread.ThreadService;
|
||||||
|
import com.foundation.web.interfaces.IThreadService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrappers the web server's framework thread service such that all webapps can use the same scheduler.
|
||||||
|
*/
|
||||||
|
public class ThreadServiceWrapper implements IThreadService {
|
||||||
|
public ThreadServiceWrapper() {
|
||||||
|
}//ThreadServiceWrapper()//
|
||||||
|
public boolean isRunning() {
|
||||||
|
return ThreadService.isRunning();
|
||||||
|
}//isRunning()//
|
||||||
|
public void run(Runnable target) {
|
||||||
|
ThreadService.run(target);
|
||||||
|
}//run()//
|
||||||
|
public void run(Runnable target, int priority) {
|
||||||
|
ThreadService.run(target, priority);
|
||||||
|
}//run()//
|
||||||
|
public Thread run(Runnable target, boolean queueable) {
|
||||||
|
return ThreadService.run(target, queueable);
|
||||||
|
}//run()//
|
||||||
|
public Thread run(Runnable target, int priority, boolean queueable) {
|
||||||
|
return ThreadService.run(target, priority, queueable);
|
||||||
|
}//run()//
|
||||||
|
}//ThreadServiceWrapper//
|
||||||
@@ -1130,7 +1130,7 @@ protected void loadWebApplications(final WebappBundle metadata) throws IOExcepti
|
|||||||
IWebApplicationFactory webApplicationFactory = (IWebApplicationFactory) cls.newInstance();
|
IWebApplicationFactory webApplicationFactory = (IWebApplicationFactory) cls.newInstance();
|
||||||
IAppLog appLog = new AppLog();
|
IAppLog appLog = new AppLog();
|
||||||
|
|
||||||
metadata.setWebApplications(webApplicationFactory.createWebApplications(metadata.getBaseDirectory(), externalApp == null || externalApp.externalBaseDirectory == null ? null : new File(externalApp.externalBaseDirectory), externalApp == null || externalApp.cacheBaseDirectory == null ? null : new File(externalApp.cacheBaseDirectory), appLog, externalApp == null ? new Properties(System.getProperties()) : externalApp.properties));
|
metadata.setWebApplications(webApplicationFactory.createWebApplications(metadata.getBaseDirectory(), externalApp == null || externalApp.externalBaseDirectory == null ? null : new File(externalApp.externalBaseDirectory), externalApp == null || externalApp.cacheBaseDirectory == null ? null : new File(externalApp.cacheBaseDirectory), appLog, new ThreadServiceWrapper(), new SchedulerWrapper(), externalApp == null ? new Properties(System.getProperties()) : externalApp.properties));
|
||||||
metadata.setWebApplicationFactory(webApplicationFactory);
|
metadata.setWebApplicationFactory(webApplicationFactory);
|
||||||
|
|
||||||
if(metadata.getWebApplications() == null) {
|
if(metadata.getWebApplications() == null) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.foundation.web.interfaces;
|
||||||
|
|
||||||
|
public interface IScheduler {
|
||||||
|
/**
|
||||||
|
* Adds a task to be executed at regular intervals.
|
||||||
|
* @param intervalTime long The amount of time in milliseconds between handler calls. How accurate the scheduler is depends on its' interval time.
|
||||||
|
* @param taskHandler Task The handler to be called at <code>intervalTime</code> intervals. If the handler takes more than a few milliseconds to complete it should start a thread of execution.
|
||||||
|
* @param runImmediatly boolean A flag that lets the scheduler know that the task should be run for the first time as soon as possible.
|
||||||
|
* @return A task reference that should be used to remove the task handler from the scheduled task list.
|
||||||
|
*/
|
||||||
|
public Object addTask(long intervalTime, Runnable taskHandler, boolean runImmediatly);
|
||||||
|
/**
|
||||||
|
* Removes a task handler so that the task will no longer be scheduled to execute.
|
||||||
|
* @param task The task to remove.
|
||||||
|
*/
|
||||||
|
public void removeTask(Object task);
|
||||||
|
/**
|
||||||
|
* Gets the running status of the scheduler.
|
||||||
|
* @return True if the scheduler is running.
|
||||||
|
*/
|
||||||
|
public boolean isRunning();
|
||||||
|
}//IScheduler//
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.foundation.web.interfaces;
|
||||||
|
|
||||||
|
public interface IThreadService {
|
||||||
|
/**
|
||||||
|
* Gets the status of the thread service.
|
||||||
|
* @return True if the thread service is running.
|
||||||
|
*/
|
||||||
|
public boolean isRunning();
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
*/
|
||||||
|
public void run(Runnable target);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param priority The thread priority.
|
||||||
|
*/
|
||||||
|
public void run(Runnable target, int priority);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param queueable Whether the thread request can be queued if there are not threads immediatly available. If the thread request is queued then the return value will be null.
|
||||||
|
* @return The reference to the thread executing the target, or null if the target was queued until a thread becomes available.
|
||||||
|
*/
|
||||||
|
public Thread run(Runnable target, boolean queueable);
|
||||||
|
/**
|
||||||
|
* Runs the target within a thread that can be reused.
|
||||||
|
* <p>CAUTION: Such methods as Thread.join() will *NOT* work properly!</p>
|
||||||
|
* @param target The target runnable given to the thread.
|
||||||
|
* @param priority The thread priority.
|
||||||
|
* @param queueable Whether the thread request can be queued if there are not threads immediatly available. If the thread request is queued then the return value will be null.
|
||||||
|
* @return The reference to the thread executing the target, or null if the target was queued until a thread becomes available.
|
||||||
|
*/
|
||||||
|
public Thread run(Runnable target, int priority, boolean queueable);
|
||||||
|
}//IThreadService//
|
||||||
@@ -13,7 +13,7 @@ public interface IWebApplicationFactory {
|
|||||||
* @param appProperties The property map containing custom properties for the web application.
|
* @param appProperties The property map containing custom properties for the web application.
|
||||||
* @return The web application.
|
* @return The web application.
|
||||||
*/
|
*/
|
||||||
public IWebApplication[] createWebApplications(File baseDirectory, File externalBaseDirectory, File cacheBaseDirectory, IAppLog log, Properties appProperties);
|
public IWebApplication[] createWebApplications(File baseDirectory, File externalBaseDirectory, File cacheBaseDirectory, IAppLog log, IThreadService threadService, IScheduler scheduler, Properties appProperties);
|
||||||
/**
|
/**
|
||||||
* Provides the factory a chance to shutdown any shared resources between the web applications, such as an Application class or thread service.
|
* Provides the factory a chance to shutdown any shared resources between the web applications, such as an Application class or thread service.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class ModelListener {
|
|||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see com.common.thread.Scheduler.Task#evaluate()
|
* @see com.common.thread.Scheduler.Task#evaluate()
|
||||||
*/
|
*/
|
||||||
public void evaluate() {
|
public void run() {
|
||||||
Binding.ObjectReference reference = null;
|
Binding.ObjectReference reference = null;
|
||||||
|
|
||||||
//Remove all bindings for objects no longer in memory.//
|
//Remove all bindings for objects no longer in memory.//
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ protected void initialize(RepositoryMetadata repositoryMetadata, IObjectAccess o
|
|||||||
getDriverClass();
|
getDriverClass();
|
||||||
|
|
||||||
Scheduler.addTask(600000, resourceCleanupTask = new Scheduler.Task() {
|
Scheduler.addTask(600000, resourceCleanupTask = new Scheduler.Task() {
|
||||||
public void evaluate() {
|
public void run() {
|
||||||
synchronized(JdbcRepositoryManager.this) {
|
synchronized(JdbcRepositoryManager.this) {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|||||||
@@ -1468,7 +1468,7 @@ public final boolean sendMessage(byte[] message, SocketData socketData, int mess
|
|||||||
protected void setupPing() {
|
protected void setupPing() {
|
||||||
if(keepAliveInterval >= 500 && keepAliveInterval <= 600000) {
|
if(keepAliveInterval >= 500 && keepAliveInterval <= 600000) {
|
||||||
setPingTask(Scheduler.addTask(keepAliveInterval, new Scheduler.Task() {
|
setPingTask(Scheduler.addTask(keepAliveInterval, new Scheduler.Task() {
|
||||||
public void evaluate() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
sendPing(false);
|
sendPing(false);
|
||||||
}//try//
|
}//try//
|
||||||
@@ -1479,7 +1479,7 @@ protected void setupPing() {
|
|||||||
//Silently die: The ping task wasn't removed.//
|
//Silently die: The ping task wasn't removed.//
|
||||||
Scheduler.removeTask(this);
|
Scheduler.removeTask(this);
|
||||||
}//catch//
|
}//catch//
|
||||||
}//evaluate()//
|
}//run()//
|
||||||
}, false));
|
}, false));
|
||||||
}//if//
|
}//if//
|
||||||
}//setupPing()//
|
}//setupPing()//
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ public class Orb {
|
|||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}//CloseSocketTask()//
|
}//CloseSocketTask()//
|
||||||
public synchronized void evaluate() {
|
public synchronized void run() {
|
||||||
if(!hasRun) {
|
if(!hasRun) {
|
||||||
Scheduler.removeTask(this);
|
Scheduler.removeTask(this);
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ public class Orb {
|
|||||||
|
|
||||||
hasRun = true;
|
hasRun = true;
|
||||||
}//if//
|
}//if//
|
||||||
}//evaluate()//
|
}//run()//
|
||||||
}//CloseSocketTask//
|
}//CloseSocketTask//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user