能否比较两个空Runnable的相等性?如何判断外部传入Runnable是否为空?
判断任意空Runnable的可行实现方案
下面给出3种不同适用场景的实现方案,可根据业务需求选择:
方案1:自定义空Runnable标记类(推荐,业务可控场景最优)
统一业务侧传入空Runnable的规范,定义一个专属的空Runnable实现类,对外公开,要求外部传入空实现时必须使用该类的实例,判断时直接用instanceof即可:
// 全局统一空Runnable实现 public final class EmptyRunnable implements Runnable { public static final EmptyRunnable INSTANCE = new EmptyRunnable(); private EmptyRunnable() {} @Override public void run() {} }
判断逻辑直接写:
public static boolean isEmptyRunnable(Runnable runnable) { return runnable instanceof EmptyRunnable; }
这种方案性能最高,没有额外开销,适合业务链路全链路可控的场景,只要对外明确传入空Runnable的规范即可。
方案2:执行后校验副作用(通用无侵入场景)
如果完全无法约束外部传入的Runnable实现,可以利用空Runnable执行无任何可观测副作用的特点判断:
public static boolean isEmptyRunnable(Runnable runnable) { if (runnable == null) return false; // 先记录当前线程的中断状态,执行后恢复 boolean originInterrupted = Thread.currentThread().isInterrupted(); try { runnable.run(); // 执行后没有抛出异常、也没有修改线程中断状态,可认为是空实现 return Thread.currentThread().isInterrupted() == originInterrupted; } catch (Throwable t) { // 执行抛出异常显然不是空实现 return false; } finally { // 恢复原本的中断状态,避免影响业务逻辑 if (originInterrupted) { Thread.currentThread().interrupt(); } else { Thread.interrupted(); } } }
注意:该方案存在边缘场景误判,比如有逻辑但最终效果和空实现完全一致的Runnable也会被判定为空,适合对准确率要求不是100%的测试场景,生产环境慎用。
方案3:字节码校验(准确率最高,适合对准确性要求高的场景)
通过反射拿到Runnable实现类的字节码,解析run方法的指令,如果只有return指令就判定为空实现:
import javassist.ClassPool; import javassist.CtMethod; public static boolean isEmptyRunnable(Runnable runnable) { if (runnable == null) return false; try { CtMethod runMethod = ClassPool.getDefault().getCtClass(runnable.getClass().getName()) .getDeclaredMethod("run"); // 获取方法指令长度,空实现的run方法指令只有return,长度为1 return runMethod.getMethodInfo().getCodeAttribute().getCodeLength() == 1; } catch (Exception e) { return false; } }
该方案需要引入javassist依赖,性能略低,但是准确率最高,几乎不会误判,适合测试场景使用。
内容的提问来源于stack exchange,提问作者Matteo NNZ
相关产品推荐
相关产品推荐

