1 package net.sf.sapjcosupport;
2
3 /**
4 * Utility class to execute a method call asynchronously.
5 * <p/>
6 * This asynchronous method invoker uses a 'pull' mechanism to await completion.
7 * The client code just calls {@link #start()} and
8 * continues doing what it needs to do. When it is ready to wait for completion of the async method,
9 * it calls {@link #waitForCompletion()}.
10 *
11 * @author Niki Driessen
12 * @since 1.0
13 */
14 public abstract class AsyncMethodCall extends Thread {
15 /**
16 * A semaphore to synchronize the start and end of the method call
17 */
18 private final Object semaphore = new Object();
19 private boolean done;
20
21 /**
22 * Implementation code of the method call.
23 * <p/>
24 * This is the code that gets executed asynchronously, when {@link #start()}
25 * is called.
26 *
27 * @see #start()
28 */
29 protected abstract void executeMethod();
30
31 /**
32 * This method is a subclassed {@link Thread#run()} method
33 * that handles executing the actual method.
34 *
35 * @see #executeMethod()
36 * @see Thread#start()
37 * @see Thread#stop()
38 * @see Thread#Thread(ThreadGroup,
39 * Runnable, String)
40 * @see Runnable#run()
41 */
42 public void run() {
43 synchronized (semaphore) {
44 try {
45 executeMethod();
46 } catch (Throwable t) {
47 t.printStackTrace();
48 } finally {
49 done = true;
50 semaphore.notifyAll();
51 }
52 }
53 }
54
55 /**
56 * Synchronization point for the asynchronous method.
57 * <p/>
58 * Call this method when you are ready to wait for the async method to
59 * complete its work. This method will block until {@link #executeMethod()} is finished
60 * (which can be the case when this method is called, and it will return immediately...)
61 */
62 public void waitForCompletion() {
63 synchronized (semaphore) {
64 while (!done) {
65 try {
66 semaphore.wait();
67 } catch (Exception e) {
68 throw new RuntimeException(e.getMessage());
69 }
70 }
71 done = false;
72 }
73 }
74
75 }