2008年6月1日星期日

事件监听器支持类

因为要写一个带事件的类,所以就写了这个东西。废话不多说,直接贴代码了:


/*

* Copyrights (C) 2008 Bearice (Bearice@Gmail.com)

* Release under GNU/GPL Version 2.

*/

package cn.bearice.java.util.listener;



import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Collections;

import java.util.EventListener;

import java.util.List;

import java.util.TreeSet;

import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



/**

* 监听器支持。

* 同于扩展特定的监听器支持类。

* <p>提供监听器的添加,获取和移除服务。提供多监听器的全同步、全异步、顺序同步,顺序异步调用。</p>

* <p>调用侦听器时不保证侦听器的调用顺序。</p>

* <p>除非特别说明,传人任何等于null的参数都将引发NullPointerException</p>

*
@author Bearice

*/

public abstract class ListenerSupport<T extends EventListener> {



protected static final ExecutorService tp = Executors.newCachedThreadPool();

protected static final ExecutorService stp = Executors.newSingleThreadExecutor();

protected Collection<T> listeners = new TreeSet<T>();



private static class ListenerCaller implements Callable<Object> {



private Method method;

private Object[] args;

private EventListener listener;



public ListenerCaller(Method method, EventListener listener, Object[] args) {

this.method = method;

this.args = args;

this.listener = listener;

}



public Object call() throws Exception {

return method.invoke(tp, args);

}

}



/**

* 添加一个侦听器。

* <p>如果侦听器已经存在,则忽略。</p>

*
@param listener 要添加的侦听器

*
@throws NullPointerException listener等于null

*/

public void addListener(T listener) {

if (listener == null) {

throw new NullPointerException();

}

if (!listeners.contains(listener)) {

listeners.add(listener);

}

}



/**

* 移除一个侦听器。

* <p>如果侦听器不存在,则忽略。</p>

*
@param listener 要移除的侦听器

*
@throws NullPointerException listener等于null

*/

public void removeListener(T listener) {

if (listener == null) {

throw new NullPointerException();

}

if (listeners.contains(listener)) {

listeners.remove(listener);

}

}



/**

* 获取所有侦听器。

* 返回一个包含所有侦听器的<b>不可修改的</b>侦听器集合副本。

* 任何针对该副本的修改操作将引发异常

*
@return 侦听器集合副本。

*/

public Collection<T> getAllListeners() {

return Collections.unmodifiableCollection(listeners);

}



/**

* 全异步调用所有侦听器。

* <p>所有侦听器将在不同的线程中同时调用,该方法不会阻塞当前线程。</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventAsync(Method method, Object... args) {

for (EventListener eventListener : listeners) {

tp.submit(new ListenerCaller(method, eventListener, args));

}

}



/**

* 全同步调用所有侦听器。

* <p>所有侦听器将在不同的线程中同时调用,该方法会阻塞当前线程并等待所有监听器调用全部返回之后才返回</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventSync(Method method, Object... args) throws InterruptedException {

List<Callable> allCallable = new ArrayList<Callable>(listeners.size());

for (EventListener eventListener : listeners) {

allCallable.add(new ListenerCaller(method, eventListener, args));

}

tp.invokeAll((Collection) allCallable);

}



/**

* 顺序异步调用所有侦听器。

* <p>所有侦听器将在相同同的线程中顺序调用,该方法不会阻塞当前线程。</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

* <p><b>调用顺序:</b>不确定调用侦听器的顺序</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventAsyncSeq(Method method, Object... args) {

for (EventListener eventListener : listeners) {

stp.submit(new ListenerCaller(method, eventListener, args));

}

}



/**

* 顺序同步调用所有侦听器。

* <p>所有侦听器将在相同的线程中顺序调用,该方法会阻塞当前线程并等待所有监听器调用全部返回之后才返回</p>

* <p><b>异常处理:</b>侦听器可以抛出任何异常,但异常将被忽略</p>

* <p><b>调用顺序:</b>不确定调用侦听器的顺序</p>

*
@param method 要调用的方法对象

*
@param args 参数

*/

protected void fireEventSyncSeq(Method method, Object... args) throws InterruptedException {

List<Callable> allCallable = new ArrayList<Callable>(listeners.size());

for (EventListener eventListener : listeners) {

allCallable.add(new ListenerCaller(method, eventListener, args));

}

stp.invokeAll((Collection) allCallable);

}

}

0 人次吐槽:

发表评论