EJB Singleton Bean是EJB 3.1规范引入的,通常用于存储缓存的数据。 这意味着,我们尝试通过使用Singleton来提高应用程序的性能。 总的来说,这很好。 特别是在并行调用不多的情况下。 但是,如果我们忽略默认锁,并且并行调用的数量增加,它就会改变。

合理的默认值

让我们从一些Java代码开始,看看如何合理设置锁。 以下代码片段显示了一个简单的带有计数器和两个方法的EJB Singleton。 method1将计数器的当前值写入日志,method2的计数从0到100。

@Singleton
@Remote(SingletonRemote.class)
public class DefaultLock implements SingletonRemote {Logger logger = Logger.getLogger(DefaultLock.class.getName());private int counter = 0;@Overridepublic void method1() {this.logger.info("method1: " + counter);}@Overridepublic void method2() throws Exception {this.logger.info("start method2");for (int i = 0; i < 100; i++) {counter++;logger.info("" + counter);}this.logger.info("end method2");}
}

如您所见,没有定义锁。 如果我们同时调用两个方法,您希望在日志文件中看到什么?

2014-06-24 21:18:51,948 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 5) method1: 0
2014-06-24 21:18:51,949 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) start method2
2014-06-24 21:18:51,949 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) 1
2014-06-24 21:18:51,949 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) 2
2014-06-24 21:18:51,950 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) 3...
2014-06-24 21:18:51,977 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) 99
2014-06-24 21:18:51,977 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) 100
2014-06-24 21:18:51,978 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 4) end method2
2014-06-24 21:18:51,978 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 6) method1: 100
2014-06-24 21:18:51,981 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 7) method1: 100
2014-06-24 21:18:51,985 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 8) method1: 100
2014-06-24 21:18:51,988 INFO  [blog.thoughts.on.java.singleton.lock.DefaultLock] (EJB default - 9) method1: 100

好的,这可能有点意外,默认是整个Singleton上的容器管理的写锁定。 这是一个很好的默认设置,以避免同时修改属性。 但是,如果我们要执行只读操作,那么这是一个糟糕的默认设置。 在这种情况下,方法调用的序列化将导致高负载下较低的可伸缩性和较低的性能。

如何避免呢?

这个问题的答案很明显,我们需要注意并发管理。 和Java EE中一样,有两种方法可以处理它。 我们可以自己做,也可以要求容器做。

Bean托管并发

我不想过多地讨论Bean管理的并发性。 这是管理并发访问的最灵活的方法。 容器允许并发访问Singleton的所有方法,并且您必须根据需要保护其状态。 这可以通过使用syncvolatile来完成。 但是要小心,很多时候这并不像看起来那样容易。

容器管理并发

容器托管并发性更易于使用,但不如Bean托管方法灵活。 但是根据我的经验,对于一般用例来说已经足够了。

正如我们在日志中看到的那样,容器管理的并发性是EJB Singleton的默认值。 容器为整个Singleton设置写锁定,并序列化所有方法调用。

我们可以更改此行为,并在方法和/或类级别上定义读写锁。 这可以通过使用@ javax.ejb.Lock(javax.ejb.LockType)注释Singleton类或方法来完成。 LockType枚举提供值WRITEREAD来定义互斥写锁定或读锁定。

以下代码片段显示了如何将method1和method2的Lock设置为LockType.READ

@Singleton
@Remote(SingletonRemote.class)
public class ReadLock implements SingletonRemote {Logger logger = Logger.getLogger(ReadLock.class.getName());private int counter = 0;@Override@Lock(LockType.READ)public void method1() {this.logger.info("method1: " + counter);}@Override@Lock(LockType.READ)public void method2() throws Exception {this.logger.info("start method2");for (int i = 0; i < 100; i++) {counter++;logger.info("" + counter);}this.logger.info("end method2");}
}

如前所述,我们可以通过使用@Lock(LockType.READ)注释类而不是同时使用这两种方法来实现相同的目的。

好的,如果一切都按预期进行,则应该并行访问这两种方法。 因此,让我们看一下日志文件。

2014-06-24 21:47:13,290 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 10) method1: 0
2014-06-24 21:47:13,291 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) start method2
2014-06-24 21:47:13,291 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 1
2014-06-24 21:47:13,291 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 2
2014-06-24 21:47:13,291 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 3...
2014-06-24 21:47:13,306 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 68
2014-06-24 21:47:13,307 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 69
2014-06-24 21:47:13,308 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 3) method1: 69
2014-06-24 21:47:13,310 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 70
2014-06-24 21:47:13,310 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 71...
2014-06-24 21:47:13,311 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 76
2014-06-24 21:47:13,311 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 77
2014-06-24 21:47:13,312 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 2) method1: 77
2014-06-24 21:47:13,312 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 78
2014-06-24 21:47:13,312 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 79...
2014-06-24 21:47:13,313 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 83
2014-06-24 21:47:13,313 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 84
2014-06-24 21:47:13,314 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 5) method1: 84
2014-06-24 21:47:13,316 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 85
2014-06-24 21:47:13,316 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 86
2014-06-24 21:47:13,317 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 87
2014-06-24 21:47:13,318 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 88
2014-06-24 21:47:13,318 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 6) method1: 89
2014-06-24 21:47:13,318 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 89
2014-06-24 21:47:13,319 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 90...
2014-06-24 21:47:13,321 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 99
2014-06-24 21:47:13,321 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) 100
2014-06-24 21:47:13,321 INFO  [blog.thoughts.on.java.singleton.lock.ReadLock] (EJB default - 1) end method2

结论

在本文开头,我们发现Java EE使用容器管理的写锁作为默认值。 这导致所有方法调用的序列化处理,并降低了应用程序的可伸缩性和性能。 在实现EJB Singleton时,我们需要牢记这一点。

我们看了两个用于控制并发管理的现有选项:Bean管理的并发和容器管理的并发。

我们使用容器托管方法为单例的这两种方法定义了一个读锁。 这不像bean管理的方法那样灵活,但是它更容易使用,并且在大多数情况下足够了。 我们只需要提供一个注释,容器将处理其余的注释。

翻译自: https://www.javacodegeeks.com/2014/06/java-ee-pitfalls-1-ignore-the-default-lock-of-a-singleton.html

Java EE陷阱#1:忽略@Singleton的默认锁定相关推荐

  1. 后端 java ee_刷新器-Java EE 7后端十大功能

    后端 java ee 这是我的小型Java EE 7复习系列的第二部分. 在进行了简要概述的第一篇介绍之后,我决定请Arjan Tijms撰写有关Java EE 7中他最喜欢的后端新功能的信息.如果您 ...

  2. 刷新器-Java EE 7后端十大功能

    这是我的Java EE 7小知识系列的第二部分. 在进行简要介绍的第一个介绍之后,我决定请Arjan Tijms撰写有关Java EE 7中他最喜欢的新后端功能的文章.如果您关注Java EE领域,您 ...

  3. java EE单例Singleton自启动

    多个单例随服务自启动(指定各个单例启动的顺序)@DependsOn("单例类名称")/@DependsOn({"单例类名称1","单例类名称2&quo ...

  4. NetBeans Java EE技巧7:忽略的Java类和XHTML编辑器快捷方式

    有时,最被忽略的是IDE最有用的功能. 在本文中,我将概述在开发Java EE应用程序时可以使用的五个NetBeans Java和XHTML编辑器快捷方式. #1 –轻松修复命名空间和类 也许您已经向 ...

  5. IBM WebSphere 开发者技术期刊: 最重要的 Java EE 最佳实践

    级别: 初级 Keys Botzum, 高级技术人员 , IBM Kyle Brown, 杰出工程师, IBM Ruth Willenborg (rewillen@us.ibm.com), 高级技术人 ...

  6. 【手把手带你学Java EE】多线程那些事,你了解了吗?

    [手把手带你学Java EE]多线程那些事,你了解了吗? 线程 概念 意义 进程和线程的区别 面试题:谈谈进程和线程的区别和联系 Java中的多线程编程 创建线程的方法 方法一 方法二 方法三 &am ...

  7. Java EE学习心得

    –Java EE学习心得   1.    称为编程专家的秘诀是: 思考-----编程--------思考------编程--.. 编程不能一步到位,不能一上来就编,必须先思考如何写,怎样写?然后再编程 ...

  8. java ee eclipse idea,转----从Eclipse转移到IntelliJ IDEA一点心得

    intellij idea.jpg 使用IntelliJ IDEA其实并不太久,用了这段时间以后,觉得的确很是好用.刚刚从Eclipse转过来的很多人开始可能不适应,我就把使用过程中的一些经验和常用功 ...

  9. jakarta_适用于Java EE / Jakarta EE开发人员的Micronaut

    jakarta 城镇中有一个名为Micronaut的新微服务框架. 在这篇文章中,我将从Java EE / Jakarta EE的角度讨论如何冒险使用Micronaut框架. 我是Java EE开发人 ...

最新文章

  1. 文巾解题383. 赎金信
  2. web前端入门学习 css(5)(浮动)(ps切图)(css属性书写顺序)(学成在线网站案例)
  3. 教育孩子的一个很棒的方式
  4. 如何成为一个Linux内核开发者
  5. Basic INFO - InstallScript脚本编程的限制
  6. 算法设计与分析——回溯法——n皇后问题
  7. EasyUI之Form load函数IE8下设置Radio或Checkbox的BUG
  8. tomcat端口被占用了怎么办
  9. 广联达登录显示服务器异常去回答,广联达设置服务器异常5
  10. Coding Interview Guide -- 判断二叉树是否为平衡二叉树
  11. VS中添加新项 数据选项卡下没有ADO.NET实体数据模型解决方案
  12. 吉大19秋学期计算机应用基础在线作业,吉大15春学期《计算机应用基础》在线作业二满分答案...
  13. 有意义的100个小故事
  14. 微信加好友CALL地址 3.4.5.27
  15. 通过ip地址连接局域网内的打印机(win7、win10)
  16. 我喜欢计算机科学作文,我爱电脑作文9篇
  17. 微博第三方+海外国际版+V2EX第三方
  18. nodejs01——安装及使用、服务端及客户端、commonjs规范、fs模块的使用(文件操作及目录操作)、stream、buffer、WebServer、端口、动态资源及静态资源、头信息、请求方式
  19. [GO] Gin入门
  20. 巴比特 | 元宇宙每日必读:连续七个季度出现亏损,Meta元宇宙部门Q2亏损28 亿美元,扎克伯格称这种情况可能会持续数年...

热门文章

  1. 服务器windows系统如何登陆,如何登陆windows云服务器
  2. ping 命令使用代理_网络检测知识篇:ping命令使用知识,你知道几点?
  3. 编译报错+解决方法:错误: 找不到符号
  4. 《线性代数及其应用》
  5. selenium自动化测试_您如何使用Selenium来计算自动化测试的投资回报率?
  6. 通过OAuth 2.0和Okta使用安全的服务器到服务器通信构建Spring Boot应用
  7. enumset_枚举集合的EnumSet
  8. jmeter测试客户端_如何在JMeter中执行客户端Web性能测试?
  9. 用Java将文件读入字节数组的7个示例
  10. 带有HttpClient的自定义HTTP标头