package cn.org.rapid_framework.util.concurrent.async; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.swing.SwingUtilities; /** * 该类主要用于得到异步方法的执行结果. * 使用示例如下. * <pre> * public void testSendEmail() { * final String address = "badqiu(a)gmail.com"; * final String subject = "test"; * final String content = "async token test"; * * //返回的token,包含token.addResponder()用于监听异步方法的执行结果 * AsyncToken token = sendAsyncEmail(address,subject,content); * * //token可以继续传递给外部,以便外面感兴趣的listener监听这个异步方法的执行结果 * token.addResponder(new IResponder() { * public void onFault(Exception fault) { * System.out.println("email send fail,cause:"+fault); * //此处可以直接引用address,subject,content,如,我们可以再次发送一次 * sendAsyncEmail(address,subject,content); * } * public void onResult(Object result) { * System.out.println("email send success,result:"+result); * } * }); * } * * public AsyncToken sendAsyncEmail(String address,String subject,String content) { * final AsyncToken token = new AsyncToken(); * * Thread thread = new Thread(new Runnable() { * public void run() { * try { * //do send email job... * token.setComplete(executeResult); //通知Responder token执行完 * }catch(Exception e) { * token.setFault(e); //通知Responder token发生错误 * } * } * }); * thread.start(); * * return token; * } * * </pre> * 生成token请查看AsyncTokenTemplate * @see AsyncTokenTemplate * @author badqiu */ public class AsyncToken<T> { public static final String DEFAULT_TOKEN_GROUP = "default"; private static AtomicLong tokenIdSequence = new AtomicLong(1); //tokenGroup tokenName tokenId private String tokenGroup = DEFAULT_TOKEN_GROUP; private String tokenName; private long tokenId; private List<IResponder> _responders = new ArrayList(2); private UncaughtExceptionHandler uncaughtExceptionHandler; private T _result; private Exception _fault; private boolean _isFiredResult; private CountDownLatch awaitResultSignal = null; public AsyncToken(){ this(null); } public AsyncToken(UncaughtExceptionHandler uncaughtExceptionHandler) { this(DEFAULT_TOKEN_GROUP,null); this.uncaughtExceptionHandler = uncaughtExceptionHandler; } public AsyncToken(String tokenGroup,String tokenName) { setTokenGroup(tokenGroup); setTokenName(tokenName); this.tokenId = tokenIdSequence.getAndIncrement(); } public String getTokenGroup() { return tokenGroup; } public void setTokenGroup(String tokenGroup) { if(tokenGroup == null) throw new IllegalArgumentException("'tokenGroup' must be not null"); this.tokenGroup = tokenGroup; } public String getTokenName() { return tokenName; } public void setTokenName(String tokenName) { this.tokenName = tokenName; } public long getTokenId() { return tokenId; } /** * 增加监听器 * addResponder(responder,false); * @param responder */ public void addResponder(final IResponder<T> responder) { addResponder(responder,false); } /** * 增加监听器,如果AsyncToken已经拥有token的执行结果, * 则token会根据invokeResponderInOtherThread参数决定是否在异步线程调用responder * @param responder 监听器 * @param invokeResponderInOtherThread true则另起线程调用responder */ public void addResponder(final IResponder<T> responder,boolean invokeResponderInOtherThread) { _responders.add(responder); if(_isFiredResult) { if(invokeResponderInOtherThread) { SwingUtilities.invokeLater(new Runnable() { public void run() { fireResult2Responder(responder); } }); }else { fireResult2Responder(responder); } } } public List<IResponder> getResponders() { return _responders; } public boolean hasResponder() { return _responders != null && _responders.size() > 0; } public UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler; } public void setUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler) { this.uncaughtExceptionHandler = uncaughtExceptionHandler; } private void fireResult2Responder(IResponder responder) { try { if(_fault != null) { responder.onFault(_fault); }else { responder.onResult(_result); } }catch(RuntimeException e) { if(getUncaughtExceptionHandler() != null) { getUncaughtExceptionHandler().uncaughtException(responder, e); }else { throw e; } }catch(Error e) { if(getUncaughtExceptionHandler() != null) { getUncaughtExceptionHandler().uncaughtException(responder, e); }else { throw e; } } } private void fireResult2Responders() { synchronized (this) { _isFiredResult = true; if(awaitResultSignal != null) { awaitResultSignal.countDown(); } } for(IResponder r : _responders) { fireResult2Responder(r); } } public void setComplete(){ setComplete(null); } public void setComplete(T result) { if(_isFiredResult) throw new IllegalStateException("token already fired"); this._result = result; fireResult2Responders(); } public void setFault(Exception fault) { if(fault == null) throw new NullPointerException(); if(_isFiredResult) throw new IllegalStateException("token already fired"); this._fault = fault; fireResult2Responders(); } public boolean isDone() { synchronized (this) { return _isFiredResult; } } /** * 等待得到token结果,测试一般使用此方法,因为jdk有相同功能的Future.get()可以使用 * @see Future */ @Deprecated public Object waitForResult() throws InterruptedException,Exception { return waitForResult(-1, null); } /** * 等待得到token结果,测试一般使用此方法,因为jdk有相同功能的Future.get()可以使用 * @see Future */ @Deprecated public Object waitForResult(long timeout,TimeUnit timeUnit) throws InterruptedException,Exception { synchronized(this) { if(_isFiredResult) { if(_fault != null) { throw _fault; }else { return _result; } } awaitResultSignal = new CountDownLatch(1); } if(timeout > 0) { awaitResultSignal.await(timeout,timeUnit); }else { awaitResultSignal.await(); } if(_fault != null) { throw _fault; }else { return _result; } } }