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 }