Skip to content

Commit

Permalink
实现异步回调库
Browse files Browse the repository at this point in the history
增加AsyncCall类,实现异步调用方法,并允许回调方法及处理异常
  • Loading branch information
jimmylab committed Dec 25, 2013
1 parent 6010390 commit 1c770c8
Show file tree
Hide file tree
Showing 3 changed files with 322 additions and 33 deletions.
136 changes: 116 additions & 20 deletions _References/ReflectTest.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,126 @@
import java.lang.reflect.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.concurrent.*;

public class ReflectTest {
@SuppressWarnings (value={"unchecked"})
public static void callback( Object object, String methodName, Object... arguments ) {
try {
Class c = object.getClass();
Class[] argTypes = new Class[arguments.length];
for ( int i=0; i<arguments.length; i++ )// {
argTypes[i] = arguments[i].getClass();
//System.out.println( argTypes[i].toString() ); }
Method m = c.getMethod("abc", argTypes);
m.invoke(object, arguments);
} catch (Throwable e) { System.out.println("Exception Occured: "); e.printStackTrace(); }
}
public static void main(String args[]) {
Object obj = new myMethods();
callback(obj, "abc", "123", "456", 789);
myMethods obj = new myMethods();
AsyncCall caller = new AsyncCall( obj, "abc", "123", "456", 789 );
//AsyncCall caller = new AsyncCall( obj, "FuckingNoExist", "123", "456", 789 );
AsyncCall[] callers = new AsyncCall[10];
for ( int i=0; i<5; i++ ) {
callers[i] = new AsyncCall( obj, "abc", "123", "456", i+1 );
callers[i].onError( obj, "abc", "Error of "+String.valueOf(i), "654", 0 );
}
for ( int i=0; i<5; i++ ) callers[i].call();
//caller.onError( obj, "abc", "987", "654", 0 );
//caller.call();
for ( int i=0; i<15; i++ ) {
System.out.println("Main running!");
try{Thread.sleep(700);}catch(InterruptedException e){}
}
caller.call();
AsyncCall.destory();
}
}
/* abstract class AsyncCall
{
} */

class myMethods
{
class myMethods {
public void abc(String arg1, String arg2, Integer arg3 ) {
if ( arg3 != 0 ) try{Thread.sleep(2000);}catch(InterruptedException e){}
System.out.println("Arguments are "+arg1+" and "+arg2+" and "+arg3+".");
if ( arg3 > 5 ) throw new myException("Error"+arg3);
}
}
class myException extends RuntimeException {
String Message;
public myException( String Msg ) { Message = Msg; }
/*@Override public void printStackTrace() {
System.out.println("Custom StackTrace with Message '"+Message+"'.");
}*/
}

@SuppressWarnings (value={"unchecked"})
class AsyncCall implements Runnable
{
static boolean Running = false;
static Thread EventLooper = null;
static LinkedBlockingDeque<AsyncTask[]> WorkLine = null;
private AsyncTask[] task;
private AsyncCall() {
if ( WorkLine ==null )
WorkLine = new LinkedBlockingDeque<AsyncTask[]>();
Running = true;
}
public AsyncCall( Object object, String methodName, Object... arguments ) {
if ( EventLooper == null ) {
AsyncCall worker = new AsyncCall();
EventLooper = new Thread(worker);
}
task = new AsyncTask[3];
task[0] = new AsyncTask( object, methodName, arguments );
}
}
public void run() {
AsyncTask[] current = null;
while ( Running ) {
while ( WorkLine.peek() != null ) {
current = WorkLine.remove();
try { current[0].Run(); }
catch (Throwable e) {
try { current[2].Run(); } catch(Throwable f){} // 一旦发生错误,调用预先设定的onError方法
continue; // 然后跳过onFinish
}
try { current[1].Run(); } catch(Throwable e){} // 一旦发生错误,调用预先设定的onError方法
}
try { Thread.sleep(1000); }
catch (InterruptedException e) { System.out.println("Interrupted!"); }
}
System.out.println("Ended!");
}
static synchronized void destory() {
if ( EventLooper != null ) {
EventLooper.interrupt();
while ( EventLooper.isAlive() ) {
if ( WorkLine.peek() == null ) Running = false;
}
EventLooper = null;
}
}
public void onFinish( Object object, String methodName, Object... arguments ) {
task[1] = new AsyncTask( object, methodName, arguments );
}
public void onError( Object object, String methodName, Object... arguments ) {
task[2] = new AsyncTask( object, methodName, arguments );
}
public void call() {
WorkLine.offer(task);
if ( !EventLooper.isAlive() )
EventLooper.start();
else
EventLooper.interrupt();
}
}
class AsyncTask {
Object object; String methodName; Object[] arguments;
public AsyncTask( Object object, String methodName, Object... arguments ) {
this.object = object; this.methodName = methodName; this.arguments = arguments;
}
public void Run() throws Throwable {
Class c = object.getClass();
Class[] argTypes = new Class[arguments.length];
try {
for ( int i=0; i<arguments.length; i++ )
argTypes[i] = arguments[i].getClass();
Method m = c.getMethod(methodName, argTypes);
try {
m.invoke(object, arguments);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
} catch (Throwable e) {
e.printStackTrace();
throw e;
}
}
}
13 changes: 0 additions & 13 deletions src/Async.lib.java

This file was deleted.

206 changes: 206 additions & 0 deletions src/AsyncCall.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;

/**
* AsyncCall类
* 异步执行与回调
* @author JimmyLiu
* @version 1.1.2
*
* 用法:
* 比如正常的调用方式为
* try {
* obj.doSomeThing("param1", "param2");
* } catch ( Throwable e ) {
* obj.errorHandler(e);
* }
* obj.Success("param1", "param2");
*
* 那么异步就应该是这样:
* AsyncCall caller = new AsyncCall( obj, "doSomeThing", "param1", "param2" ); // 顺序为:对象,方法名,参数列表
* caller.onError( obj, "errorHandler" );
* caller.onSuccess( obj, "obj.Success", "param1", "param2" );
* caller.call();
*
* 注意事项:类本身也作为轮询线程使用,万万不要手贱去调用run()方法【有意思吗】
* 程序(主线程)退出前务必用@see AsyncCall#destroy 方法擦屁股!(否则你就会发现程序永远退不出呵呵)
*/
@SuppressWarnings (value={"unchecked"})
public class AsyncCall implements Runnable
{
public static void main(String args[]) {
myMethods obj = new myMethods();
AsyncCall caller = new AsyncCall( obj, "abc", "123", "456", 789 );
//AsyncCall caller = new AsyncCall( obj, "FuckingNoExist", "123", "456", 789 );
AsyncCall[] callers = new AsyncCall[10];
for ( int i=0; i<5; i++ ) {
callers[i] = new AsyncCall( obj, "abc", "123", "456", i+1 );
callers[i].onError( obj, "Er" );
}
for ( int i=0; i<5; i++ ) callers[i].call();
//caller.onError( obj, "abc", "987", "654", 0 );
//caller.call();
for ( int i=0; i<15; i++ ) {
System.out.println("Main running!");
try{Thread.sleep(700);}catch(InterruptedException e){}
}
caller.call();
AsyncCall.destory();
}
private static boolean Running = false; // 运行状态
private static Thread EventLooper = null; // 事件轮询线程
private static LinkedBlockingDeque<AsyncTask[]> WorkLine = null; // 任务流水线队列
private AsyncTask[] task; // 任务数组,方法本身+onSuccess+onError
/**
* AsyncCall
* 默认构造函数(私有的!只能用于内部建立线程用)
*/
private AsyncCall() {
if ( WorkLine ==null )
WorkLine = new LinkedBlockingDeque<AsyncTask[]>(); // 初始化流水线
Running = true;
}
/**
* AsyncCall
* 构造函数(公有),设定要异步执行的方法
* @param Object object 要执行的对象
* @param String methodName 要执行的方法名
* @param Object... arguments 要传递的参数
*/
public AsyncCall( Object object, String methodName, Object... arguments ) {
task = new AsyncTask[3];
task[0] = new AsyncTask( object, methodName, arguments );
}
/**
* run
* 当把类作为轮询线程时,才用此run方法,请勿直接调用!
* @return void
*/
public void run() { // 当把类作为轮询线程时,有此run方法
AsyncTask[] current = null;
while ( Running ) {
while ( WorkLine!=null && WorkLine.peek() != null ) {
current = WorkLine.remove();
try { current[0].Run(); }
catch (Throwable e) {
try { current[2].Run(e); } catch(Throwable f){} // 一旦发生错误,调用预先设定的onError方法,并将异常交给第一参数,但onError方法中自身的错误将被忽略,包括onError方法为空的情况
continue; // 然后跳过onSuccess,包括onSuccess方法为空的情况
}
try { current[1].Run(); } catch(Throwable e){} // onSuccess方法中自身的错误将被忽略
}
try { Thread.sleep(30000); } // 休息30秒,让出CPU控制权
catch (InterruptedException e) { continue; } // 反之则被吵醒,继续轮询
}
}
/**
* onSuccess
* 指定执行成功时的回调函数
* @param Object object 要执行的对象
* @param String methodName 要执行的方法名
* @param Object... arguments 要传递的参数
* @return void
*/
public void onSuccess( Object object, String methodName, Object... arguments ) {
task[1] = new AsyncTask( object, methodName, arguments );
}
/**
* onError
* 指定执行时发生异常的回调函数
* @param Object object 要执行的对象
* @param String methodName 要执行的方法名
* @return void
* 注意:处理错误的方法,只能拥有一个类型为Throwable的参数,用于接收异常的句柄
*/
public void onError( Object object, String methodName ) {
Throwable err = new Throwable();
task[2] = new AsyncTask( object, methodName, err );
}
/**
* call
* 开始执行任务
* @return void
*/
public void call() {
if ( EventLooper == null ) { // 如果轮询线程死亡态或为null(下面称僵尸态^_^)
AsyncCall worker = new AsyncCall();
EventLooper = new Thread(worker);
EventLooper.start(); // 开启新线程
call(); // 再次尝试回调
} else {
WorkLine.offer(task); // 反之将任务加入队列,
EventLooper.interrupt(); // 并试图吵醒轮询线程
}
}
/**
* (static) destory
* 停止轮询线程,回收一切有关AsyncCall的资源
* @return void
*/
static void destory() {
if ( EventLooper != null && EventLooper.isAlive() ) { // 若线程不僵尸……
EventLooper.interrupt(); // 吵醒线程
while ( WorkLine.peek() != null ) { // 默默等待流水线完成……
try { Thread.sleep(10); } catch (InterruptedException e){ } // 每次等待10ms
}
while ( EventLooper.isAlive() ) { // 只要线程还没停
Running = false; // 置运行状态为停止
EventLooper.interrupt(); // 又吵醒(>_<)
}
EventLooper = null;
WorkLine = null; // 擦屁股操作
}
}
}

/**
* AsyncTask结构体
* 异步任务的载体
* @author JimmyLiu
* @version 1.1
*/
class AsyncTask {
Object object; String methodName; Object[] arguments;
/**
* AsyncTask
* 构造函数
* @param Object object 要执行的对象引用
* @param String methodName 要执行的方法名
* @param Object... arguments 要传递的参数
*/
public AsyncTask( Object object, String methodName, Object... arguments ) {
this.object = object; this.methodName = methodName; this.arguments = arguments;
}
/**
* Run
* 执行承载的任务,利用Java的反射机制
* @param Throwable err = null 要接收异常类的变量,可选
* @return void
* @throws Throwable 抛出回调函数中发生的异常或者,包括但不限于
* - 方法无法调用:NoSuchMethodException、NullPointerException、SecurityException
* - 尝试调用时的错误:NullPointerException,IllegalAccessException,IllegalArgumentException,ExceptionInInitializerError
*/
public void Run(Throwable err) throws Throwable {
Class c = object.getClass();
Class[] argTypes = new Class[arguments.length];
try {
for ( int i=0; i<arguments.length; i++ ) {
argTypes[i] = arguments[i].getClass(); // 逐一获取每个参数的类型
}
Method m = c.getMethod(methodName, argTypes); // 寻找匹配的方法
try {
m.invoke(object, arguments); // 尝试执行
}
catch (InvocationTargetException e) { // 如果回调函数本身抛出异常
throw e.getTargetException(); // 则获取并抛出源异常
}
} catch (Throwable e) {
//e.printStackTrace(); // 这时其实你可以追踪堆栈
if ( err != null) err = e;
throw e; // 再次抛出
}
}
public void Run() throws Throwable {
Run(null);
}
}

0 comments on commit 1c770c8

Please sign in to comment.