1 package com.explosion.utilities.process.threads;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.Date;
24
25 import org.apache.log4j.LogManager;
26 import org.apache.log4j.Logger;
27
28 import com.explosion.utilities.process.ProcessMonitor;
29 /***
30 * This class provides a simple way to control processes. IE start stop etc.
31 * It provides very simple logic too; the run method does the following
32 *
33 * 1) process.initialise
34 * 2) while alive or not finished, process.process()
35 * 3) process.finalise
36 *
37 * @author Stephen
38 * Created on 26-Jun-2004
39 */
40 public class SimpleProcessThread implements ProcessThread
41 {
42 private static Logger log = LogManager.getLogger(SimpleProcessThread.class);
43
44
45 private int interval = 10;
46
47 private int priority = Thread.NORM_PRIORITY;
48
49 private Thread executionThread;
50
51 private Thread thisThread;
52
53
54 private boolean finalised = false;
55
56 private com.explosion.utilities.process.threads.SimpleProcess process;
57
58 private Date startTime = null;
59
60 private Date endTime = null;
61
62 private int status = THREAD_NOT_YET_STARTED;
63
64 private boolean wasKilled = false;
65
66 private boolean join = false;
67
68 /***
69 * For an explanation on implementing safely stoppable and suspendable
70 * threads please see
71 *
72 * @see http://java.sun.com/products/jdk/1.2/docs/guide/misc/threadPrimitiveDeprecation.html
73 */
74 public void run()
75 {
76 try
77 {
78 thisThread = Thread.currentThread();
79
80 checkSuspended();
81
82 if (process == null)
83 {
84 log.warn("No process specified, exiting simple process control.");
85 return;
86 }
87
88 ProcessMonitor.registerProcess(this, process.isUserProcess());
89
90 process.initialise();
91
92 checkSuspended();
93
94
95 while (executionThread == thisThread && process.getPercentComplete() < 100)
96 {
97 checkSuspended();
98 if (status == THREAD_STOPPED) break;
99
100 process.process();
101
102 checkSuspended();
103 if (status == THREAD_STOPPED) break;
104
105
106 try
107 {
108 if (interval > 0) Thread.sleep(interval);
109 } catch (InterruptedException e)
110 {}
111 }
112
113 process.finalise();
114 } catch (Exception ex)
115 {
116 if (process != null)
117 process.finalise(ex);
118 }
119
120 try {
121 stop();
122 } catch (InterruptedException e) {
123
124 log.error("Interrupted",e);
125 }
126
127
128 status = THREAD_COMPLETED;
129 }
130
131 /***
132 * Performs suspend logic if the thread has been suspended
133 */
134 public void checkSuspended()
135 {
136
137 if (status == THREAD_SUSPENDED)
138 {
139 synchronized (this)
140 {
141 while (status == THREAD_SUSPENDED && executionThread == thisThread)
142 {
143 try
144 {
145 wait();
146 } catch (InterruptedException e)
147 {}
148 }
149 }
150 }
151 }
152
153 /***
154 * Starts the job. If join has been specified then this method will not return until the job has finished.
155 */
156 public void start()
157 {
158 status = THREAD_STARTED;
159 startTime = new Date();
160
161 executionThread = new Thread(this);
162 executionThread.setPriority(priority);
163 executionThread.start();
164
165 try
166 {
167 if (join)
168 executionThread.join();
169 }
170 catch (InterruptedException e)
171 {
172 }
173 }
174
175 /***
176 * This parameter needs to be set before the process is started. If set to true, the
177 * process will call thread.join and will not return from the start method until the run thread is finished.
178 * @param join
179 */
180 public void setJoin(boolean join)
181 {
182 this.join = join;
183 }
184
185
186 /***
187 * Stop the job
188 */
189 public synchronized void stop() throws InterruptedException
190 {
191 if (!(status == THREAD_STOPPED))
192 {
193 executionThread = null;
194 notify();
195 endTime = new Date();
196 status = THREAD_STOPPED;
197 }
198
199 thisThread.interrupt();
200 if (executionThread != null)
201 executionThread.interrupt();
202
203 if (executionThread != null && executionThread.isAlive())
204 {
205 executionThread.stop();
206 }
207 }
208
209 /***
210 * Ssuspend the job.
211 */
212 public synchronized void suspend()
213 {
214 status = THREAD_SUSPENDED;
215 }
216
217 /***
218 * Restart the job.
219 */
220 public synchronized void resume()
221 {
222 status = THREAD_STARTED;
223 notifyAll();
224 }
225
226 /***
227 * This method allows the user to set the Thread priority of this
228 * controllable object. Possible priorities are: a) Thread.NORM_PRIORITY, b)
229 * Thread.MAX_PRIORITY c) Thread.MIN_PRIORITY The default priority is
230 * Thread.NORM_PRIORITY.
231 */
232 public void setPriority(int priority)
233 {
234 this.priority = priority;
235 }
236
237 /***
238 * This method allows the user to set the interval between each thread loop.
239 * Default is 10 (0.001 seconds);
240 */
241 public void setInterval(int interval)
242 {
243 this.interval = interval;
244 }
245
246 /***
247 * Set the UnitisedProcess for this UnitisedProcess
248 */
249 public void setProcess(com.explosion.utilities.process.threads.Process process)
250 {
251 this.process = (SimpleProcess) process;
252 }
253
254 /***
255 * Gets the process for this UnitisedProcess
256 */
257 public com.explosion.utilities.process.threads.Process getProcess()
258 {
259 return process;
260 }
261
262 /***
263 * This method returns the actual thread object upon which this Runnable
264 * object is operating.
265 */
266 public Thread getRunThread()
267 {
268 return thisThread;
269 }
270
271 /***
272 * This method returns status of the thread
273 */
274 public int getStatus()
275 {
276 return status;
277 }
278
279 /***
280 * Kills the job
281 */
282 public void kill()
283 {
284 try {
285 stop();
286 } catch (InterruptedException e) {
287
288 log.error("Interrupted",e);
289 }
290 wasKilled = true;
291 }
292
293 /***
294 * Returns whether or not the job was killed
295 */
296 public boolean wasKilled()
297 {
298 return wasKilled;
299 }
300
301 }
302