Browse Source

REPORT-83195 卡顿点优化-回退一下开发者模式部分代码,设计有点问题

feature/x
John.Ying-应志浩 1 year ago
parent
commit
5155311b6e
  1. 75
      designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java
  2. 73
      designer-base/src/main/java/com/fr/design/carton/developer/AwtEventInfo.java
  3. 141
      designer-base/src/main/java/com/fr/design/carton/developer/EventDispatchDeveloperMode.java

75
designer-base/src/main/java/com/fr/design/carton/SwitchForSwingChecker.java

@ -1,7 +1,6 @@
package com.fr.design.carton;
import com.fr.design.carton.developer.EventDispatchDeveloperMode;
import com.fr.design.i18n.Toolkit;
import com.fr.general.GeneralUtils;
import com.fr.json.JSON;
@ -30,22 +29,11 @@ import java.util.Map;
import java.util.Date;
import java.util.Calendar;
public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
/**
* Designer4Debug类名
*/
private static final String DEBUG_MAIN_CLASS_NAME = "com.fr.start.Designer4Debug";
/**
* 真正主类
*/
private static final String NORMAL_MAIN_CLASS_NAME = "com.fr.start.MainDesigner";
/**
* 开发者模式jvm参数
*/
private static final String CARTON_DEVELOPER_JVM_PARAM = "cartonDeveloper";
/**
* XML标签
*/
@ -58,7 +46,6 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
* 简单记录事件执行时间的开关
*/
private static boolean easyChecker = false;
/**
* 一个标识位用于区分耗时任务时长检测(简单检测)和timer检测
*/
@ -262,7 +249,11 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
*/
public static void initThreadMonitoring () {
String mainClass = System.getProperty("sun.java.command");
MainClassType.getMainClassType(mainClass).initEventQueue();
//判断一下,如果是以Designer4Debug启动,就不注册代码,不然会覆盖掉SwingExplorer,导致其无法使用
if (!StringUtils.equals(mainClass, DEBUG_MAIN_CLASS_NAME)) {
EventDispatchThreadHangMonitor.initMonitoring();
AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool());
}
}
/**
@ -318,60 +309,4 @@ public class SwitchForSwingChecker implements XMLReadable, XMLWriter {
writer.end();
}
/**
* 根据程序启动类路径进行区分
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/14
*/
enum MainClassType {
/**
* 用mainDesigner启动
*/
MAIN(NORMAL_MAIN_CLASS_NAME) {
@Override
void initEventQueue() {
if (StringUtils.equals(TURE_JVM, System.getProperty(CARTON_DEVELOPER_JVM_PARAM))) {
EventDispatchDeveloperMode.INSTANCE.initMonitoring();
} else {
EventDispatchThreadHangMonitor.initMonitoring();
AppContext.getAppContext().put(SwingWorker.class, CartonThreadExecutorPool.getTimerThreadExecutorPool());
}
}
},
/**
* designer4debug启动
*/
DEBUG_MAIN(DEBUG_MAIN_CLASS_NAME) {
@Override
void initEventQueue() {
}
};
MainClassType(String classPath) {
this.classPath = classPath;
}
public static final String TURE_JVM = "true";
String classPath;
/**
* 初始化重写的EDT
*/
abstract void initEventQueue();
/**
* @param classPath 启动类路径
*/
static MainClassType getMainClassType(String classPath) {
for (MainClassType mainClassType : MainClassType.values()) {
if (StringUtils.equals(classPath, mainClassType.classPath)) {
return mainClassType;
}
}
return MAIN;
}
}
}

73
designer-base/src/main/java/com/fr/design/carton/developer/AwtEventInfo.java

@ -1,73 +0,0 @@
package com.fr.design.carton.developer;
import java.awt.AWTEvent;
/**
* EDT事件的包装类,用来额外处理信息
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/14
*/
public class AwtEventInfo {
//获取执行该事件的线程
private final Thread eventDispatchThread = Thread.currentThread();
//在队列中等待执行的事件最后未执行的时间,当有一个事件执行完后就遍历dispatches给该值赋当前时间
private long lastDispatchTimeMillis = System.currentTimeMillis();
//事件开始的时间
private final long startDispatchTimeMillis = System.currentTimeMillis();
//awt事件
private AWTEvent awtEvent;
//事件堆栈
private StackTraceElement[] stackTrace;
/**
* 检查是否要给堆栈赋值
*/
public void checkForHang() {
if (isNeedToStackTrace()) {
this.stackTrace = eventDispatchThread.getStackTrace();
}
}
/**
* 是否需要赋值堆栈满足
* 耗时>20ms
*/
private boolean isNeedToStackTrace() {
return (System.currentTimeMillis() - startDispatchTimeMillis) > EventDispatchDeveloperMode.MAX_TIME
&& stackTrace == null;
}
public Thread getEventDispatchThread() {
return eventDispatchThread;
}
public long getLastDispatchTimeMillis() {
return lastDispatchTimeMillis;
}
public void setLastDispatchTimeMillis(long lastDispatchTimeMillis) {
this.lastDispatchTimeMillis = lastDispatchTimeMillis;
}
public long getStartDispatchTimeMillis() {
return startDispatchTimeMillis;
}
public AWTEvent getAwtEvent() {
return awtEvent;
}
public void setAwtEvent(AWTEvent awtEvent) {
this.awtEvent = awtEvent;
}
public StackTraceElement[] getStackTrace() {
return stackTrace;
}
public void setStackTrace(StackTraceElement[] stackTrace) {
this.stackTrace = stackTrace;
}
}

141
designer-base/src/main/java/com/fr/design/carton/developer/EventDispatchDeveloperMode.java

@ -1,141 +0,0 @@
package com.fr.design.carton.developer;
import com.aspose.words.Run;
import com.fr.concurrent.FineExecutors;
import com.fr.design.carton.EventDispatchThreadHangMonitor;
import com.fr.design.ui.util.UIUtil;
import com.fr.log.FineLoggerFactory;
import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 开发者模式重写的EDT
*
* @author John.Ying
* @since 11.0
* Created on 2023/4/14
*/
public final class EventDispatchDeveloperMode extends EventQueue {
/**
* 该链表为主要的实现定时任务的容器在重写的dispatchEvent中由pre方法将DispatchInfo加入到链表由post方法remove
*/
private final LinkedList<AwtEventInfo> dispatches = new LinkedList<>();
/**
* 开启间隔检测后两次检测的相隔时间ms
*/
public static final long CHECK_INTERVAL_MS = 5;
private static final int CORE_THREAD_SIZE = 1;
private ScheduledExecutorService timer;
/**
* edt事件最大允许的时间
*/
public static final long MAX_TIME = 20;
public static final EventDispatchDeveloperMode INSTANCE = new EventDispatchDeveloperMode();
@Override
protected void dispatchEvent(AWTEvent event) {
try {
preDispatchEvent(event);
super.dispatchEvent(event);
} finally {
postDispatchEvent();
}
}
/**
* 事件分发前处理
*/
private synchronized void preDispatchEvent(AWTEvent event) {
synchronized (dispatches) {
AwtEventInfo awtEventInfo = new AwtEventInfo();
awtEventInfo.setAwtEvent(event);
dispatches.addLast(awtEventInfo);
}
}
/**
* 事件分发后处理
*/
private synchronized void postDispatchEvent() {
synchronized (dispatches) {
AwtEventInfo awtEventInfo = dispatches.removeLast();
//嵌套最深的事件执行完毕后刷新链表中其他事件的lastDispatchTimeMillis
Thread currentEventDispatchThread = Thread.currentThread();
for (AwtEventInfo info : dispatches) {
info.setLastDispatchTimeMillis(System.currentTimeMillis());
}
long nowTime = System.currentTimeMillis();
long totalTime = nowTime - awtEventInfo.getStartDispatchTimeMillis();
long continuationTime = nowTime - awtEventInfo.getLastDispatchTimeMillis();
//判断连续执行时间是否超过了20ms,超过了则进行提示
if (continuationTime > MAX_TIME) {
FineLoggerFactory.getLogger()
.warn("awt event spend time more than 20ms, totalTime {} continuationTime {} the stack is {}"
, totalTime, continuationTime, EventDispatchThreadHangMonitor.stackTraceToStringForConsole(awtEventInfo.getStackTrace()));
}
}
}
/**
* 将swing中默认的EventQueue换成自己的
*/
public void initMonitoring() {
UIUtil.invokeLaterIfNeeded(() -> Toolkit.getDefaultToolkit().getSystemEventQueue().push(INSTANCE));
initTimer();
startFilterModalWindow();
}
/**
* Sets up a timer to check for hangs frequently.
* 初始化一个Timer
*/
public void initTimer() {
final long initialDelayMs = 0;
timer = FineExecutors.newScheduledThreadPool(CORE_THREAD_SIZE);
timer.schedule(() -> {
synchronized (dispatches) {
//如果链表为空定时检测就不进行
if (dispatches.isEmpty()) {
return;
}
dispatches.getLast().checkForHang();
}
}, initialDelayMs, TimeUnit.MILLISECONDS);
}
/**
* /消除Timer
*/
public void stopTimer() {
if (timer != null) {
timer.shutdown();
}
}
/**
* 消除模态框影响
*/
public void startFilterModalWindow() {
ScheduledExecutorService scheduledExecutorService = FineExecutors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
UIUtil.invokeLaterIfNeeded(() -> {
//不用干事,切个片就可以
});
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
}
Loading…
Cancel
Save