Skip to content

Commit 2c24e2a

Browse files
committed
Organize code; add event exception handling interface; add corresponding test items;
1 parent ff7f846 commit 2c24e2a

File tree

5 files changed

+159
-18
lines changed

5 files changed

+159
-18
lines changed

src/main/java/net/lamgc/utils/event/EventExecutor.java

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public class EventExecutor {
2222

2323
private Thread.UncaughtExceptionHandler exceptionHandler = null;
2424

25+
private EventUncaughtExceptionHandler eventExceptionHandler = null;
26+
2527
/**
2628
* 构造一个EventExecutor.
2729
* @param threadPoolExecutor 事件线程池, 线程池将用于执行Handler中的EventMethod.
@@ -45,6 +47,15 @@ public EventExecutor(ThreadPoolExecutor threadPoolExecutor,
4547
Thread newThread = threadFactory.newThread(r);
4648
if(newThread.getUncaughtExceptionHandler() == newThread.getThreadGroup()){
4749
newThread.setUncaughtExceptionHandler((t, e) -> {
50+
if(e instanceof EventInvokeException && eventExceptionHandler != null){
51+
EventInvokeException exception = (EventInvokeException) e;
52+
eventExceptionHandler.exceptionHandler(
53+
exception.getHandler(),
54+
exception.getHandlerMethod(),
55+
exception.getEventObject(),
56+
exception.getCause());
57+
return;
58+
}
4859
if(this.exceptionHandler != null){
4960
this.exceptionHandler.uncaughtException(t, e);
5061
}
@@ -88,15 +99,7 @@ public void executor(final EventObject eventObject){
8899
}
89100
eventHandlerMethod.forEach(method -> {
90101
final Set<EventHandler> handlerSet = eventHandlerObjectMap.getHandlerObject(method.getDeclaringClass());
91-
threadPoolExecutor.execute(() -> handlerSet.forEach(handler -> {
92-
try {
93-
method.invoke(handler, eventObject);
94-
} catch (IllegalAccessException e) {
95-
throw new RuntimeException(e);
96-
} catch (InvocationTargetException e){
97-
throw new RuntimeException(e.getCause() == null ? e : e.getCause());
98-
}
99-
}));
102+
threadPoolExecutor.execute(() -> handlerSet.forEach(handler -> executeEvent(handler, eventObject, method)));
100103
});
101104
}
102105

@@ -122,20 +125,24 @@ public int executor(EventHandler handler, EventObject eventObject){
122125
continue;
123126
}
124127

125-
threadPoolExecutor.execute(() -> {
126-
try {
127-
method.invoke(handler, eventObject);
128-
} catch (IllegalAccessException e) {
129-
throw new RuntimeException(e);
130-
} catch (InvocationTargetException e){
131-
throw new RuntimeException(e.getCause() == null ? e : e.getCause());
132-
}
133-
});
128+
executeEvent(handler, eventObject, method);
134129
invokeCount++;
135130
}
136131
return invokeCount;
137132
}
138133

134+
private void executeEvent(EventHandler handler, EventObject event, Method eventMethod){
135+
threadPoolExecutor.execute(() -> {
136+
try {
137+
eventMethod.invoke(handler, event);
138+
} catch (IllegalAccessException e) {
139+
throw new RuntimeException(e);
140+
} catch (InvocationTargetException e){
141+
throw new EventInvokeException(handler, eventMethod, event, e.getCause());
142+
}
143+
});
144+
}
145+
139146
/**
140147
* 等待线程池内任务执行完成并关闭线程池.
141148
* @param timeout 时间
@@ -149,8 +156,12 @@ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedE
149156

150157
/**
151158
* 设置线程池异常处理类.
159+
*
152160
* EventExecutor在内部经过处理,
153161
* 可以动态更改UncaughtExceptionHandler而不用担心设置后需要等线程重新建立后才生效.
162+
* 注意: 如需捕获EventHandler方法抛出的异常请使用{@link #setEventUncaughtExceptionHandler(EventUncaughtExceptionHandler)},
163+
* 设置捕获EventHandler抛出的异常, 因EventExecutor内部处理,
164+
* UncaughtExceptionHandler无法捕获{@link InvocationTargetException}异常来获取事件方法抛出的异常.
154165
* @param handler 处理类对象
155166
*/
156167
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler handler){
@@ -187,6 +198,32 @@ public List<Runnable> shutdown(boolean shutdownNow){
187198
}
188199
}
189200

201+
/**
202+
* 设置事件异常捕获处理对象.
203+
* 该对象能详细获得
204+
* @param handler 事件异常捕获处理对象
205+
*/
206+
public void setEventUncaughtExceptionHandler(EventUncaughtExceptionHandler handler){
207+
this.eventExceptionHandler = handler;
208+
}
209+
210+
/**
211+
* 事件异常处理接口
212+
*/
213+
@FunctionalInterface
214+
public interface EventUncaughtExceptionHandler{
215+
216+
/**
217+
* 当事件对象抛出异常时触发.
218+
* @param handler 事件处理方法所在{@link EventHandler}
219+
* @param handlerMethod 抛出异常的方法对象
220+
* @param event 事件对象
221+
* @param cause 异常对象
222+
*/
223+
void exceptionHandler(EventHandler handler, Method handlerMethod, EventObject event, Throwable cause);
224+
}
225+
226+
190227
@Override
191228
protected void finalize() {
192229
threadPoolExecutor.shutdownNow();
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package net.lamgc.utils.event;
2+
3+
import java.lang.reflect.Method;
4+
5+
public class EventInvokeException extends RuntimeException {
6+
7+
private EventHandler handler;
8+
9+
private Method handlerMethod;
10+
11+
private EventObject eventObject;
12+
13+
private Throwable cause;
14+
15+
public EventInvokeException(EventHandler handler, Method handlerMethod, EventObject event, Throwable cause){
16+
super();
17+
this.handler = handler;
18+
this.handlerMethod = handlerMethod;
19+
this.eventObject = event;
20+
this.cause = cause;
21+
}
22+
23+
public EventHandler getHandler() {
24+
return handler;
25+
}
26+
27+
public void setHandler(EventHandler handler) {
28+
this.handler = handler;
29+
}
30+
31+
public EventObject getEventObject() {
32+
return eventObject;
33+
}
34+
35+
public void setEventObject(EventObject eventObject) {
36+
this.eventObject = eventObject;
37+
}
38+
39+
@Override
40+
public Throwable getCause() {
41+
return cause;
42+
}
43+
44+
public void setCause(Throwable cause) {
45+
this.cause = cause;
46+
}
47+
48+
public Method getHandlerMethod() {
49+
return handlerMethod;
50+
}
51+
52+
public void setHandlerMethod(Method handlerMethod) {
53+
this.handlerMethod = handlerMethod;
54+
}
55+
}

src/test/java/net/lamgc/utils/event/EventExecutorTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,33 @@ public void executorTest() throws IllegalAccessException, InterruptedException {
3838
executor.executor(new SimpleEventObject(2, "HelloWorld123"));
3939
}
4040

41+
@Test
42+
public void caughtExceptionTest() throws IllegalAccessException, InterruptedException {
43+
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
44+
1,
45+
Runtime.getRuntime().availableProcessors() / 2,
46+
30L, TimeUnit.SECONDS,
47+
new ArrayBlockingQueue<>(10)
48+
);
49+
threadPoolExecutor.setRejectedExecutionHandler((r, executor) -> {
50+
try {
51+
executor.getQueue().put(r);
52+
} catch (InterruptedException e) {
53+
throw new RuntimeException(e);
54+
}
55+
});
56+
EventExecutor executor = new EventExecutor(threadPoolExecutor);
4157

58+
executor.setEventUncaughtExceptionHandler((handler, handlerMethod, event, cause) -> {
59+
System.out.println("Handler: " + handler.toString() + ", MethodName: " + handlerMethod.getName() +
60+
", Event: " + event.getClass().getSimpleName() + " throw Exception: " + cause.getMessage());
61+
cause.printStackTrace();
62+
});
63+
64+
SimpleEventHandler handler = new SimpleEventHandler("handler1");
65+
executor.addHandler(handler);
66+
executor.executor(new ExceptionThrowEvent(new NullPointerException()));
67+
Thread.sleep(1000L);
68+
}
4269

4370
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package net.lamgc.utils.event;
2+
3+
public class ExceptionThrowEvent implements EventObject {
4+
5+
private Throwable exception;
6+
7+
public ExceptionThrowEvent(Throwable exception){
8+
this.exception = exception;
9+
}
10+
11+
public Throwable getException() {
12+
return exception;
13+
}
14+
15+
public void setException(Throwable exception) {
16+
this.exception = exception;
17+
}
18+
}

src/test/java/net/lamgc/utils/event/SimpleEventHandler.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@ public void simpleEventHandler(SimpleEventObject event){
1212
System.out.println(this.toString() + "." + flag + " - [" + event.errorCode + "] " + event.msg);
1313
}
1414

15+
public void throwExceptionEvent(ExceptionThrowEvent event){
16+
throw new RuntimeException(event.getException());
17+
}
18+
1519
}

0 commit comments

Comments
 (0)