Java 的Event机制浅析

来源:互联网 发布:论文数据来源怎么标注 编辑:程序博客网 时间:2024/06/03 20:39

    通常java添加监听类似C里面的回调,通常在使用时比较简单,自己定义的事件类(继承EventObject),定义监听
器接口(继承EventListener),定义一个者向量来保存添加的这些监听器,通过addListenerremoveListener来操作。

但是监听器如何被触发的,从底层消息到启动监听器的流程是什么样子的?

将分篇来说明,下面以一个BossXi ,BossLi类来说明:

添加EmployeeEvent事件类:
package Company;import java.util.EventObject;public class EmployeeEvent extends EventObject{private int m_nReason;private int m_nType;private Object m_sSource;public EmployeeEvent(Object arg0,int reason , int type) {super(arg0);// TODO Auto-generated constructor stubthis.setType(type);this.m_nReason = reason;this.m_sSource = arg0;}/** *  */private static final long serialVersionUID = 1L;public static final int EVENT_WORK_ON = 0;public static final int EVENT_WORK_OFF = 1;public int getReason(){return m_nReason;}public int getType(){return m_nType;}public int setType(int nType){return this.m_nType = nType;}public Object getSource(){return (java.lang.Object)m_sSource;}}

添加EmployeeListener监听接口:
package Company;// 实现 EventListener接口public interface EmployeeListener extends java.util.EventListener{// 使用监听器的时候,实现并添加到public void onEmPloyeeEvent(EmployeeEvent empEvent);}

添加分发消息接口MessageHandler:
package Company;public interface MessageHandler {  public void processMessage(Message message);  }

添加消息Message类:
package Company;public class Message {  public final static int TerminateType = -1;  public int type;  public Object data;  MessageHandler handler;  public Message(MessageHandler p, int t, Object d)  {    handler = p;    type = t;    data = d;  }  public boolean equals(Object o)  {    Message e = (Message) o;    return ((handler == e.handler) && (type == e.type) &&            data.equals(e.data));  }}

添加队列轮询线程PollThread类:
package Company;import java.util.Vector;public class PollThread extends Thread{private static int nThreadCounts;private static Object syncObj = new Object();    private Vector<Message> messageQueue=new Vector<Message>();    private Object messageSignal=new Object();    protected boolean runing=false;    String name;        static {    setnThreadCounts(0);        }        public PollThread(String name){    super(name);    this.name = name;    synchronized(syncObj){    setnThreadCounts(getnThreadCounts() + 1);        }    }public static int getnThreadCounts() {return nThreadCounts;}public static void setnThreadCounts(int nThreadCounts) {PollThread.nThreadCounts = nThreadCounts;}        public void addMessage(Message message){        if(message==null){        return;    }    synchronized(messageSignal){        messageQueue.add(message);        messageSignal.notifyAll();    }    }        public boolean removeMessage(Message message){    boolean bRet;    if(message==null){        return false;    }    synchronized(messageSignal){    bRet = messageQueue.remove(message);    }    return bRet;    }        private Message getMessage(){    Message msg = null;    synchronized (messageSignal){    while (messageQueue.size() == 0) {try {messageSignal.wait();} catch (InterruptedException e) {// TODO: handle exceptione.printStackTrace();}}}    msg = (Message)messageQueue.get(0);messageQueue.remove(0);return msg;    }        public synchronized void waitRun(){    while (!runing) {try {this.wait();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}    }        public void run(){Message msg = null;synchronized (this) {runing = true;this.notifyAll();}while (true) {try {msg = getMessage();if (msg != null) {if(msg.handler == null &&   msg.type == Message.TerminateType &&   msg.data == messageSignal){   break;   }   msg.handler.processMessage(msg);}} catch (Exception e) {// TODO: handle exceptionif (true) {e.printStackTrace();}}}}}

添加EventManager类:
package Company;import java.util.Enumeration;import java.util.Vector;public abstract class EventManager implements MessageHandler{protected PollThread pollThread;protected Vector listeners = new Vector();public static int ECASTER_MESSAGE_TYPE;//protected Vector<EmployeeListener> listeners = new Vector<EmployeeListener>();public EventManager(String string) {// TODO Auto-generated method stubpollThread = new PollThread("PollThread" + string);pollThread.start();pollThread.waitRun();}public void addListener(Object oListener){if (oListener == null) {return ;}for (int i = 0; i < listeners.size(); i++) {if(oListener == listeners.get(i)){return ;}}listeners.add(oListener);}public int size(){return listeners.size();}public void removeListener(Object oListener){if (oListener == null) {return ;}listeners.remove(oListener);}public void removeAllListener(){listeners.clear();}public void castEvent(Object event){if (event == null) {return;}Message Msg = new Message(this, ECASTER_MESSAGE_TYPE, event);if(pollThread == null){pollThread = new PollThread("PollThread" + "EventManager");pollThread.start();pollThread.waitRun();}pollThread.addMessage(Msg);}protected abstract void processEvent(Object listener, Object event); // 由该类的继承类实现public void processMessage(Message msg){    Object listener = null;    Object event = null;        if(msg.type!=ECASTER_MESSAGE_TYPE){        return;    }        Vector listeners_bak = (Vector)listeners.clone();    event = msg.data;    for (Enumeration e = listeners_bak.elements(); e.hasMoreElements();) {    listener = e.nextElement();    if (listener == null) {continue;}try {processEvent(listeners_bak, event);  // 触发引用上注册的监听器} catch (Exception e2) {// TODO: handle exceptionif (true) {e2.printStackTrace();}}}}  }

添加EmployeeEventCast类:
package Company;public class EmployeeEventCast extends EventManager{public EmployeeEventCast(String name) {super(name);// TODO Auto-generated constructor stub}@Overrideprotected void processEvent(Object listener, Object event) {// TODO Auto-generated method stubEmployeeListener slistener = (EmployeeListener)listener;EmployeeEvent eevent = (EmployeeEvent)event;slistener.onEmPloyeeEvent(eevent);  // 触发应用注册的监听器}}

添加BossXi ,BossLi 类:
package Company;public class BossXi {EmployeeEventCast eCast;//  代理的方式来处理event消息public void addLister(EmployeeListener eaddpListener) {eCast.addListener(eaddpListener);}public void removeListener(EmployeeListener emoveListener){eCast.removeListener(emoveListener);}// 老板向雇员发消息 , 也即向轮询线程添加消息addMessagepublic void castEventToEmployee(EmployeeEvent event){eCast.castEvent(event);}}

package Company;// 通过继承EventManager,自己来完成消息的添加public class BossLi extends EventManager{public BossLi(String string) {super(string);// TODO Auto-generated constructor stub}@Overrideprotected void processEvent(Object listener, Object event) {// TODO Auto-generated method stubEmployeeListener slistener = (EmployeeListener)listener;EmployeeEvent eevent = (EmployeeEvent)event;slistener.onEmPloyeeEvent(eevent);  // 触发应用注册的监听器}public void addLister(EmployeeListener eaddpListener) {super.addListener(eaddpListener);}public void removeListener(EmployeeListener emoveListener){super.removeListener(emoveListener);}// 老板向雇员发消息 , 也即向轮询线程添加消息addMessagepublic void castEventToEmployee(EmployeeEvent event){super.castEvent(event);}}

测试代码:
package Company;public class Test {public static EmployeeListener eListener;public static BossXi bossXi = new BossXi();public static BossLi bossLi = new BossLi("BossLi");public static void main(){// 实现监听器回调eListener = new EmployeeListener() {@Overridepublic void onEmPloyeeEvent(EmployeeEvent empEvent) {// TODO Auto-generated method stubint event = empEvent.getReason();System.out.print("Event is " + "[" + event + "]");switch (event) {case EmployeeEvent.EVENT_WORK_OFF:System.out.print("Boss call me to work off!! ");break;case EmployeeEvent.EVENT_WORK_ON:System.out.print("Boss call me to work on!! ");break;default:break;}}};// 习老板添加监听器bossXi.addLister(eListener);// 上班事件EmployeeEvent eventon = new EmployeeEvent(bossXi ,EmployeeEvent.EVENT_WORK_ON, EventManager.ECASTER_MESSAGE_TYPE);// 下班事件EmployeeEvent eventoff = new EmployeeEvent(bossXi ,EmployeeEvent.EVENT_WORK_OFF, EventManager.ECASTER_MESSAGE_TYPE);// 习老板喊人干活bossXi.eCast.castEvent(eventon);// 习老板喊人干活bossXi.eCast.castEvent(eventoff);bossLi.addListener(eListener);bossLi.castEvent(eventon);bossLi.castEvent(eventoff);}}


应用主要是使用这个BossLi,BossXi 两个类来添加对应时间的监听

PollThread 是一个轮询线程,专门在Message消息队列里面取最新消息,并触发监听器,调用注册的监听回调

轮询线程轮询的是消息队列的消息,消息队列的消息从哪里来,来了之后作什么用?
通过以上例子,
首先,我们姑且把BossLi 或者BossXi成消息产生的源头,通过castEvent -->  addMessage 将消息添加到消息队列;
其次,消息和事件之间如何建立联系,上面例子中是在创建一个消息会传入对应的event事件值,并且提供一个包含分发消息hander(此处是继承接口MessageHandler的一个类);
接着,pollThread 将消息队列里面的消息取出来,利用消息里面已有的processMessage方法来来派发event事件

其实我们还可以在BossLi 或者 BossXi 里面添加JNI方法,收到C层的回调时,来向消息队列里面添加消息,然后在转成event
发给应用的监听器,关键是打通JNI和java,能从jni调到java方法。








0 0
原创粉丝点击