Java 的Event机制浅析


    通常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 stub
		this.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 exception
					e.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 exception
				e.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 exception
				if (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 stub
		pollThread = 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 exception
				if (true) {
					e2.printStackTrace();
				}
			}
		}
	}
	  
}

添加EmployeeEventCast类:
package Company;

public class EmployeeEventCast extends EventManager{

	public EmployeeEventCast(String name) {
		super(name);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void processEvent(Object listener, Object event) {
		// TODO Auto-generated method stub
		EmployeeListener 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);
	}
	
	// 老板向雇员发消息 , 也即向轮询线程添加消息addMessage
	public 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
	}

	@Override
	protected void processEvent(Object listener, Object event) {
		// TODO Auto-generated method stub
		EmployeeListener 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);		
	}
	
	// 老板向雇员发消息 , 也即向轮询线程添加消息addMessage
	public 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() {			
			@Override
			public void onEmPloyeeEvent(EmployeeEvent empEvent) {
				// TODO Auto-generated method stub
				int 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方法。








你可能感兴趣的:(java,event)