1 package org.feistymeow.process;
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
7 * A simple java thread that hearkens back to the HOOPLE C++ ethread in features.
9 * @author Chris Koeritz
10 * @copyright Copyright (c) 2010-$now By Feisty Meow Concerns Ltd.
11 * @license This file is free software; you can modify and redistribute it under the terms of the
12 * Apache License v2.0: http://www.apache.org/licenses/LICENSE-2.0
14 public abstract class ethread implements Runnable
16 private static Log c_logger = LogFactory.getLog(ethread.class);
18 // the actual java thread object.
19 private volatile Thread c_RealThread = null;
20 // provides synchronization for the thread.
21 private volatile Object c_lock = new Object();
22 // this is the timing period, for a timed thread. if zero, then this is a single shot thread.
23 private long c_period = 0;
24 // records whether the thread should shut down or not.
25 private boolean c_stopThread = false;
26 // snooze between checks on the stop timer.
27 final long SNOOZE_PERIOD = 20;
30 * creates a new single-shot ethread without starting it. this type of thread will run just
38 * creates a new periodic ethread without starting it. this type of thread runs every "period"
39 * milliseconds until stopped or until the performActivity method returns false.
41 public ethread(long period)
47 * this is the main function that derived classes must implement. it does the actual work that
48 * the thread is intended to perform. note that the derived version must not do anything to
49 * cause the thread to be ripped out while performActivity is still being invoked. the return
50 * value should be true if the thread can continue executing. this is meaningless for single
51 * shot threads executed via runOnce, but matters for the periodic threads started with
54 abstract public boolean performActivity();
57 * Begins execution of the thread.
61 synchronized (c_lock) {
62 if (null == this.c_RealThread) {
63 this.c_RealThread = new Thread(this);
64 c_logger.debug("starting thread " + c_RealThread.getId());
65 this.c_RealThread.start();
71 * Stops execution of the thread, or at least attempts to.
80 } catch (InterruptedException e) {
81 // ignoring this since we'll keep snoozing as needed.
90 * Signals the thread to stop executing, but does not wait for it.
94 synchronized (c_lock) {
96 Thread goAway = c_RealThread;
105 * Returns true if the thread object is still alive. this does not necessarily mean it is currently active.
107 public boolean threadAlive()
109 synchronized (c_lock) {
110 return this.c_RealThread != null;
115 * returns true if the thread has been told to stop running.
117 public boolean shouldStop()
119 synchronized (c_lock) {
125 * this is the override from Runnable that allows us to call our own performActivity method.
126 * implementors should not override this; they should override performActivity instead.
131 if (!threadAlive()) {
132 return; // stopped before it ever started. how can this be? we just got invoked.
136 boolean keepGoing = performActivity();
138 c_logger.debug("thread returned false for single shot thread. just saying.");
141 // not a periodic thread, so we're done now.
144 long nextRun = System.currentTimeMillis() + c_period;
145 while (System.currentTimeMillis() < nextRun) {
150 Thread.sleep(SNOOZE_PERIOD);
151 } catch (InterruptedException e) {
152 // well, we'll hit it again soon.
156 } catch (Throwable t) {
157 c_logger.info("exception thrown from performActivity: " + t.getLocalizedMessage(), t);