对于那些使用第三方工具来尝试扩展它们而又不完全了解它们的人来说,这是一个小技巧。 假定以下情况:

  • 您想扩展一个公开分层数据模型的库(假设您要扩展Apache Jackrabbit )
  • 该库在访问内容存储库的任何节点之前会内部检查访问权限
  • 您想实现自己的访问控制算法
  • 您的访问控制算法将访问内容存储库的其他节点
  • …反过来又会触发访问控制
  • …进而将再次访问内容存储库的其他节点

…无限递归,如果不递归广度优先,则可能会导致StackOverflowError 。

现在,您有两个选择:

  1. 花时间,坐下来,了解内部原理,并正确地做。 到达自己的扩展名后,您可能不应该递归到访问控制中。 在扩展Jackrabbit的情况下,这可以通过使用系统会话来进一步访问访问控制算法中的节点来完成。 系统会话通常绕过访问控制。
  2. 急躁,想快速获得结果,并通过技巧来防止递归

当然,您确实应该选择选项1。但是,谁有时间了解所有内容?

这是实现该技巧的方法。

/*** This thread local indicates whether you've* already started recursing with level 1*/
static final ThreadLocal<Boolean> RECURSION_CONTROL= new ThreadLocal<Boolean>();/*** This method executes a delegate in a "protected"* mode, preventing recursion. If a inadvertent* recursion occurred, return a default instead*/
public static <T> T protect(T resultOnRecursion,Protectable<T> delegate)
throws Exception {// Not recursing yet, allow a single level of// recursion and execute the delegate onceif (RECURSION_CONTROL.get() == null) {try {RECURSION_CONTROL.set(true);return delegate.call();}finally {RECURSION_CONTROL.remove();}}// Abort recursion and return earlyelse {return resultOnRecursion;}
}/*** An API to wrap your code with*/
public interface Protectable<T> {T call() throws Exception;
}

在此用法示例中可以很容易地看出这一点:

public static void main(String[] args)
throws Exception {protect(null, new Protectable<Void>() {@Overridepublic Void call() throws Exception {// Recurse infinitelySystem.out.println("Recursing?");main(null);System.out.println("No!");return null;}});
}

main()方法的递归调用将被保护方法终止,并提早返回,而不是执行call() 。 也可以通过使用ThreadLocals Map进一步详细说明此思想,从而允许指定各种键或上下文以防止递归。 然后,您还可以将Integer放入ThreadLocal ,在递归时将其递增,最多允许N个递归级别。

static final ThreadLocal<Integer> RECURSION_CONTROL= new ThreadLocal<Integer>();public static <T> T protect(T resultOnRecursion,Protectable<T> delegate)
throws Exception {Integer level = RECURSION_CONTROL.get();level = (level == null) ? 0 : level;if (level < 5) {try {RECURSION_CONTROL.set(level + 1);return delegate.call();}finally {if (level > 0)RECURSION_CONTROL.set(level - 1);elseRECURSION_CONTROL.remove();}}else {return resultOnRecursion;}
}

但是再说一次。 也许您应该再花几分钟时间,了解主机库的内部机制是如何工作的,并从一开始就将事情做好……与往常一样,在使用技巧和黑客手段时!

参考:在Java,SQL和JOOQ博客上,我们的JCG合作伙伴 Lukas Eder 提供了Java ThreadLocals的意外递归保护 。

翻译自: https://www.javacodegeeks.com/2013/04/inadvertent-recursion-protection-with-java-threadlocals.html

使用Java ThreadLocals的意外递归保护相关推荐

  1. java 递归改非递归_使用Java ThreadLocals的意外递归保护

    java 递归改非递归 对于那些使用第三方工具来尝试扩展它们而又不完全了解它们的人来说,这是一个小技巧. 假定以下情况: 您想扩展一个展示分层数据模型的库(假设您要扩展Apache Jackrabbi ...

  2. mysql vue 菜谱_vue+ java 实现多级菜单递归效果

    效果如图: 大概思路:树形视图使用的是vue官方事例代码,java负责封装数据,按照vue官方事例的数据结构封装数据即可.有两个需要关注的点: 1.官方事例的数据结构是一个对象里面包含着集合,而不是一 ...

  3. Java入门算法(递归篇)丨蓄力计划

    本专栏已参加蓄力计划,感谢读者支持 往期文章 一. Java入门算法(贪心篇)丨蓄力计划 二. Java入门算法(暴力篇)丨蓄力计划 三. Java入门算法(排序篇)丨蓄力计划 四. Java入门算法 ...

  4. java 什么时候用递归_如果要用Java实现算法,一定慎用递归

    现象 : 递归是我们很经典的一种算法实现,可以很好的描述一个算法的原理!对于算法的描述.表现和代码结构理解上,递归都是不错的选择! 但是本文想说的是java实现一个递归算法的时候尽量不要用递归实现,而 ...

  5. java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误

    文章目录 1.报错信息 2.原因分析 3.解决方案 1.报错信息 java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误 ORA-01000: 超出打开游 ...

  6. java递归实现多级菜单栏_vue+ java 实现多级菜单递归效果

    效果如图: 大概思路:树形视图使用的是vue官方事例代码,java负责封装数据,按照vue官方事例的数据结构封装数据即可.有两个需要关注的点: 1.官方事例的数据结构是一个对象里面包含着集合,而不是一 ...

  7. 又出问题 三星Galaxy S10被曝意外触摸保护功能无效

    [TechWeb]3月16日,据外媒报道,有用户在三星美国社区论坛反应新三星Galaxy S10系列产品手机上的意外触摸保护功能无效,这导致了用户意外拨号和电池消耗加快等问题. Galaxy S10用 ...

  8. 用java编写一个故事的程序_使用Java怎么编写一个递归程序

    使用Java怎么编写一个递归程序 发布时间:2021-02-20 16:05:44 来源:亿速云 阅读:52 作者:Leah 这篇文章将为大家详细讲解有关使用Java怎么编写一个递归程序,文章内容质量 ...

  9. Java数据结构和算法 - 递归

    三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,--中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...

最新文章

  1. 合并BN层到卷积层的原理及实验
  2. c 语言现代方法13章习题6
  3. mysql自增长主键_MySQL数据库8(九)列属性之主键、自增长
  4. Exchanger及其用法
  5. linux 创建用户和修改新增用户默认的家目录
  6. 这年头「野路子」产品太多了
  7. 【实践】对比学习在快手推荐系统中的的应用探索
  8. 思科称其安全设备易受 SNIcat 数据渗透攻击
  9. 使用半透明的DIV实现禁用页面功能
  10. 【转】listView中,checkBox的显示和隐藏
  11. Eclipse的界面语言
  12. LeetCode之猜数字大小
  13. C#调用C语言生成的DLL“未找到入口”
  14. 字体编辑用中日韩汉字Unicode编码表
  15. Tuxedo中间件介绍
  16. Autovue 21.0.2.3 新功能介绍
  17. 如何方便输入德语、法语、俄语特殊字符
  18. python设计一个学生类姓名年龄成绩_C# 编写学生类Student,包含学生姓名,成绩,设计一个友员函数sortDegree(),将学生成绩按大到小排序。...
  19. java ajax 导入excel_通过ajax上传excel
  20. 河南计算机教师资格证,河南教师资格证考试科目

热门文章

  1. MySQL存储过程+游标+触发器
  2. java 函数式编程 示例_功能Java示例 第1部分–从命令式到声明式
  3. oracle查看jdk文档_Oracle JDK 9 Early Access文档已更新
  4. aix pax_通过Pax考试对JBoss Fuse 6.x进行集成测试,第一部分
  5. java编译器jdk版本_以编程方式确定Java类的JDK编译版本
  6. Java中带有NetSuite数据实体的对象关系映射(ORM)
  7. Java线程的不同状态
  8. Oracle发布Java 8
  9. maven ant_如何在Maven中运行Ant目标?
  10. 使用正确的垃圾收集器将Java内存使用量降至最低