feisty meow concerns codebase  2.140
ethread.java
Go to the documentation of this file.
1 package org.feistymeow.process;
2 
3 import org.apache.commons.logging.Log;
4 import org.apache.commons.logging.LogFactory;
5 
14 public abstract class ethread implements Runnable
15 {
16  private static Log c_logger = LogFactory.getLog(ethread.class);
17 
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;
28 
32  public ethread()
33  {
34  }
35 
40  public ethread(long period)
41  {
42  c_period = period;
43  }
44 
51  abstract public boolean performActivity();
52 
56  public void start()
57  {
58  synchronized (c_lock) {
59  if (null == this.c_RealThread) {
60  this.c_RealThread = new Thread(this);
61  c_logger.debug("starting thread " + c_RealThread.getId());
62  this.c_RealThread.start();
63  }
64  }
65  }
66 
70  public void stop()
71  {
72  cancel();
73  while (true) {
74  if (threadAlive()) {
75  try {
76  Thread.sleep(40);
77  } catch (InterruptedException e) {
78  // ignoring this since we'll keep snoozing as needed.
79  }
80  } else {
81  break;
82  }
83  }
84  }
85 
89  void cancel()
90  {
91  synchronized (c_lock) {
92  c_stopThread = true;
93  Thread goAway = c_RealThread;
94  c_RealThread = null;
95  if (null != goAway) {
96  goAway.interrupt();
97  }
98  }
99  }
100 
104  public boolean threadAlive()
105  {
106  synchronized (c_lock) {
107  return this.c_RealThread != null;
108  }
109  }
110 
114  public boolean shouldStop()
115  {
116  synchronized (c_lock) {
117  return c_stopThread;
118  }
119  }
120 
125  @Override
126  public void run()
127  {
128  if (!threadAlive()) {
129  return; // stopped before it ever started. how can this be? we just got invoked.
130  }
131  try {
132  while (true) {
133  boolean keepGoing = performActivity();
134  if (!keepGoing) {
135  c_logger.debug("thread returned false, signifying it wants to exit. now dropping it.");
136  break;
137  }
138  if (c_period == 0) {
139  // not a periodic thread, so we're done now.
140  break;
141  }
142  long nextRun = System.currentTimeMillis() + c_period;
143  while (System.currentTimeMillis() < nextRun) {
144  if (shouldStop()) {
145  break;
146  }
147  try {
148  Thread.sleep(SNOOZE_PERIOD);
149  } catch (InterruptedException e) {
150  // well, we'll hit it again soon.
151  }
152  }
153  }
154  } catch (Throwable t) {
155  c_logger.info("exception thrown from performActivity: " + t.getLocalizedMessage(), t);
156  }
157  // reset the thread held since we're leaving right now.
158  c_stopThread = true;
159  c_RealThread = null;
160  }
161 }
abstract boolean performActivity()