当前位置: 首页 > news >正文

模板网站和定聚企360做的网站

模板网站和定,聚企360做的网站,企业全称网站,做招聘和求职都需要哪些网站从我过去有关性能的文章和HashMap案例研究中可能已经看到#xff0c;Java线程安全性问题可以很轻松地使Java EE应用程序和Java EE容器崩溃。 在对Java EE性能问题进行故障排除时#xff0c;我观察到的最常见问题之一是由非线程安全的HashMap get#xff08;#xff09;和pu… 从我过去有关性能的文章和HashMap案例研究中可能已经看到Java线程安全性问题可以很轻松地使Java EE应用程序和Java EE容器崩溃。 在对Java EE性能问题进行故障排除时我观察到的最常见问题之一是由非线程安全的HashMap get和put操作触发的无限循环。 这个问题已经有好几年了但是最近的生产问题迫使我不得不再次讨论这个问题。 本文将重温这个经典的线程安全问题并使用一个简单的Java程序演示与并发线程上下文中涉及的普通旧java.util.HashMap数据结构的错误使用有关的风险。 此概念验证练习将尝试实现以下三个目标 重新访问和比较非线程安全和线程安全Map数据结构实现HashMapHashtable同步的HashMapConcurrentHashMap之间的Java程序性能级别 使用每个人都可以编译运行和理解的简单Java程序复制并演示HashMap无限循环问题 回顾上述Map数据结构在现实和现代Java EE容器实现例如JBoss AS7中的用法 有关ConcurrentHashMap实现策略的更多详细信息我强烈推荐Brian Goetz撰写的出色文章。 工具和服务器规格 首先请找到以下用于练习的不同工具和软件 Sun / Oracle JDK和JRE 1.7 64位 Eclipse Java EE IDE Windows Process Explorer每个Java线程关联的CPU JVM线程转储阻塞的线程分析和每个线程的CPU相关性 以下本地计算机用于问题复制过程和性能测量 英特尔R酷睿TM i5-2520M CPU 2.50Ghz2个CPU内核4个逻辑内核 8 GB内存 Windows 7 64位 * Java程序的结果和性能可能会因您的工作站或服务器规格而异。 Java程序 为了帮助我们实现上述目标按如下方式创建了一个简单的Java程序 Java主程序是HashMapInfiniteLoopSimulator.java 还创建了一个工作线程类WorkerThread.java 该程序正在执行以下操作 初始化大小为2的不同静态Map数据结构 将选定的Map分配给工作线程您可以在4个Map实现中进行选择 创建一定数量的工作线程根据标头配置。 为此概念证明创建了3个工作线程NB_THREADS 3; 这些工作线程中的每一个都有相同的任务使用介于1到1000000之间的随机 Integer元素查找并在分配的Map数据结构中插入新元素。 每个辅助线程执行此任务共计500K次迭代 整个程序执行50次迭代以便为HotSpot JVM提供足够的启动时间 并发线程上下文是使用JDK ExecutorService实现的 如您所见Java程序任务相当简单但是足够复杂以生成以下关键条件 针对共享/静态Map数据结构生成并发 混合使用get和put操作以尝试触发内部锁和/或内部损坏对于非线程安全的实现 使用较小的Map初始大小2强制内部HashMap触发内部重新哈希/调整大小 最后可以方便地修改以下参数 ##工作线程数 private static final int NB_THREADS 3; ## Java程序迭代次数 private static final int NB_TEST_ITERATIONS 50; ##地图数据结构分配。 您可以选择4种结构 // Plain old HashMap (since JDK 1.2) threadSafeMap1 new HashtableString, Integer(2);// Plain old Hashtable (since JDK 1.0) threadSafeMap1 new HashtableString, Integer(2);// Fully synchronized HashMap threadSafeMap2 new HashMapString, Integer(2); threadSafeMap2 Collections.synchronizedMap(threadSafeMap2);// ConcurrentHashMap (since JDK 1.5) threadSafeMap3 new ConcurrentHashMapString, Integer(2);/*** Assign map at your convenience ****/ assignedMapForTest threadSafeMap3; 现在在下面找到我们示例程序的源代码。 #### HashMapInfiniteLoopSimulator.java package org.ph.javaee.training4;import java.util.Collections; import java.util.Map; import java.util.HashMap; import java.util.Hashtable;import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** HashMapInfiniteLoopSimulator* author Pierre-Hugues Charbonneau**/ public class HashMapInfiniteLoopSimulator {private static final int NB_THREADS 3;private static final int NB_TEST_ITERATIONS 50;private static MapString, Integer assignedMapForTest null;private static MapString, Integer nonThreadSafeMap null;private static MapString, Integer threadSafeMap1 null;private static MapString, Integer threadSafeMap2 null;private static MapString, Integer threadSafeMap3 null;/*** Main program* param args*/public static void main(String[] args) {System.out.println(Infinite Looping HashMap Simulator);System.out.println(Author: Pierre-Hugues Charbonneau);System.out.println(http://javaeesupportpatterns.blogspot.com);for (int i0; iNB_TEST_ITERATIONS; i) {// Plain old HashMap (since JDK 1.2)nonThreadSafeMap new HashMapString, Integer(2);// Plain old Hashtable (since JDK 1.0)threadSafeMap1 new HashtableString, Integer(2);// Fully synchronized HashMapthreadSafeMap2 new HashMapString, Integer(2);threadSafeMap2 Collections.synchronizedMap(threadSafeMap2);// ConcurrentHashMap (since JDK 1.5)threadSafeMap3 new ConcurrentHashMapString, Integer(2); // ConcurrentHashMap/*** Assign map at your convenience ****/assignedMapForTest threadSafeMap3;long timeBefore System.currentTimeMillis();long timeAfter 0;Float totalProcessingTime null;ExecutorService executor Executors.newFixedThreadPool(NB_THREADS);for (int j 0; j NB_THREADS; j) {/** Assign the Map at your convenience **/Runnable worker new WorkerThread(assignedMapForTest);executor.execute(worker); }// This will make the executor accept no new threads// and finish all existing threads in the queueexecutor.shutdown();// Wait until all threads are finishwhile (!executor.isTerminated()) {}timeAfter System.currentTimeMillis();totalProcessingTime new Float( (float) (timeAfter - timeBefore) / (float) 1000);System.out.println(All threads completed in totalProcessingTime seconds);}}}#### WorkerThread.java package org.ph.javaee.training4;import java.util.Map;/*** WorkerThread** author Pierre-Hugues Charbonneau**/ public class WorkerThread implements Runnable {private MapString, Integer map null;public WorkerThread(MapString, Integer assignedMap) {this.map assignedMap;}Overridepublic void run() {for (int i0; i500000; i) {// Return 2 integers between 1-1000000 inclusiveInteger newInteger1 (int) Math.ceil(Math.random() * 1000000);Integer newInteger2 (int) Math.ceil(Math.random() * 1000000); // 1. Attempt to retrieve a random Integer elementInteger retrievedInteger map.get(String.valueOf(newInteger1));// 2. Attempt to insert a random Integer elementmap.put(String.valueOf(newInteger2), newInteger2); }}} 线程安全的Map实现之间的性能比较 第一个目标是比较使用不同线程安全的Map实现时我们程序的性能水平 普通的旧哈希表自JDK 1.0起 完全同步的HashMap通过Collections.synchronizedMap ConcurrentHashMap自JDK 1.5起 在下面找到每个迭代的Java程序执行的图形结果以及程序控制台输出示例。 使用ConcurrentHashMap时的输出 Infinite Looping HashMap Simulator Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com All threads completed in 0.984 seconds All threads completed in 0.908 seconds All threads completed in 0.706 seconds All threads completed in 1.068 seconds All threads completed in 0.621 seconds All threads completed in 0.594 seconds All threads completed in 0.569 seconds All threads completed in 0.599 seconds ……………… 如您所见ConcurrentHashMap在这里显然是赢家所有3个工作线程平均仅花费半秒在初始启动后就可以针对指定的共享Map并在500K循环语句中同时读取和插入数据。 请注意程序执行没有问题例如没有挂起情况。 性能的提高肯定是由于ConcurrentHashMap性能的提高例如无阻塞的get操作。 其他2个Map实现的性能水平非常相似但对于同步的HashMap而言却具有很小的优势。 HashMap无限循环问题复制 下一个目标是复制从Java EE生产环境中经常观察到的HashMap无限循环问题。 为此您只需要按照下面的代码片段分配非线程安全的HashMap实现即可 /*** Assign map at your convenience ****/ assignedMapForTest nonThreadSafeMap; 使用非线程安全的HashMap按原样运行程序应导致 除程序头外无输出 从系统观察到的CPU大量增加 Java程序有时会挂起您将被迫杀死Java进程 发生了什么 为了了解这种情况并确认问题我们将使用Process Explorer和JVM Thread Dump从Windows操作系统执行每个线程的CPU分析。 1 –再次运行程序然后按照以下方法从Process Explorer快速捕获每个CPU数据的线程。 在explorer.exe下您需要右键单击javaw.exe并选择属性。 将显示“线程”选项卡。 我们可以看到几乎所有系统CPU都使用了4个线程。 2 –现在您必须使用JDK 1.7 jstack实用程序快速捕获JVM线程转储。 对于我们的示例我们可以看到我们的3个工作线程它们似乎忙/忙于执行get和put操作。 ..\jdk1.7.0\binjstack 272 2012-08-29 14:07:26 Full thread dump Java HotSpot(TM) 64-Bit Server VM (21.0-b17 mixed mode):pool-1-thread-3 prio6 tid0x0000000006a3c000 nid0x18a0 runnable [0x0000000007ebe000]java.lang.Thread.State: RUNNABLEat java.util.HashMap.put(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:32)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source)pool-1-thread-2 prio6 tid0x0000000006a3b800 nid0x6d4 runnable [0x000000000805f000]java.lang.Thread.State: RUNNABLEat java.util.HashMap.get(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:29)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source)pool-1-thread-1 prio6 tid0x0000000006a3a800 nid0x2bc runnable [0x0000000007d9e000]java.lang.Thread.State: RUNNABLEat java.util.HashMap.put(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:32)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) .............. 现在该按照以下方法将Process Explorer线程ID DECIMAL格式转换为HEXA格式。 HEXA值使我们可以按照以下方式映射和标识每个线程 ## TID1748nid 0X6D4 线程名称pool-1-thread-2 CPU 25.71 任务工作线程执行HashMap.get操作 at java.util.HashMap.get(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:29)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) ## TID700nid 0X2BC 线程名称pool-1-thread-1 CPU 23.55 任务工作线程执行HashMap.put操作 at java.util.HashMap.put(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:32)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) ## TID6304nid 0X18A0 线程名称pool-1-thread-3 CPU 12.02 任务工作线程执行HashMap.put操作 at java.util.HashMap.put(Unknown Source)at org.ph.javaee.training4.WorkerThread.run(WorkerThread.java:32)at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source) ## TID5944nid 0X1738 线程名称pool-1-thread-1 CPU 20.88 任务主Java程序执行 main prio6 tid0x0000000001e2b000 nid0x1738 runnable [0x00000000029df000]java.lang.Thread.State: RUNNABLEat org.ph.javaee.training4.HashMapInfiniteLoopSimulator.main(HashMapInfiniteLoopSimulator.java:75) 如您所见上面的相关性和分析非常有启发性。 我们的主要Java程序处于挂起状态因为我们的3个工作线程正在占用大量CPU并且无法正常运行。 它们在执行HashMap get和put时可能看起来“卡住”但实际上它们都涉及无限循环条件。 这正是我们想要复制的内容。 HashMap无限循环深入探究 现在让我们进一步分析以更好地了解这种循环条件。 为此我们在JDK 1.7 HashMap Java类本身中添加了跟踪代码以了解正在发生的情况。 为put操作添加了类似的日志记录还添加了一条跟踪指示内部和自动重新哈希/调整大小已触发。 在get和put操作中添加的跟踪使我们能够确定for循环是否正在处理循环依赖关系这将解释无限循环条件。 #### HashMap.java get() operation public V get(Object key) {if (key null)return getForNullKey();int hash hash(key.hashCode());/*** P-H add-on- iteration counter ***/int iterations 1;for (EntryK,V e table[indexFor(hash, table.length)];e ! null;e e.next) {/*** Circular dependency check ***/EntryK,V currentEntry e;EntryK,V nextEntry e.next;EntryK,V nextNextEntry e.next ! null?e.next.next:null;K currentKey currentEntry.key; K nextNextKey nextNextEntry ! null?(nextNextEntry.key ! null?nextNextEntry.key:null):null;System.out.println(HashMap.get() #Iterations : iterations);if (currentKey ! null nextNextKey ! null ) { if (currentKey nextNextKey || currentKey.equals(nextNextKey))System.out.println( ** Circular Dependency detected! [currentEntry][nextEntry]][nextNextEntry]);}/***** END ***/Object k;if (e.hash hash ((k e.key) key || key.equals(k)))return e.value;}return null;}HashMap.get() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.resize() in progress... HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 2 HashMap.resize() in progress... HashMap.resize() in progress... HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 2 HashMap.put() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.put() #Iterations : 1** Circular Dependency detected! [362565362565][333326333326]][362565362565] HashMap.put() #Iterations : 2** Circular Dependency detected! [333326333326][362565362565]][333326333326] HashMap.put() #Iterations : 1 HashMap.put() #Iterations : 1 HashMap.get() #Iterations : 1 HashMap.put() #Iterations : 1 ............................. HashMap.put() #Iterations : 56823 再次添加的日志记录非常有启发性。 我们可以看到在几个内部HashMap.resize之后内部结构受到了影响创建了循环依赖条件并触发了这个无限循环条件#iterations不断增加和增加……而没有退出条件。 这也表明resize/ rehash操作最容易遭受内部损坏尤其是当使用默认的HashMap大小16时。这意味着HashMap的初始大小似乎是造成风险的重要因素。问题复制。 最后有趣的是我们能够通过将初始大小设置为1000000来成功运行非线程安全HashMap的测试用例从而完全避免了任何调整大小。 在合并图结果下方找到 HashMap是我们表现最好的但是仅在防止内部调整大小时才使用。 同样这绝对不是解决线程安全风险的方法而只是一种方法表明考虑到当时执行的HashMap的整个操作调整大小操作的风险最大。 到目前为止ConcurrentHashMap是我们的整体赢家因为它针对该测试用例提供了快速的性能和线程安全性。 JBoss AS7 Map数据结构用法 现在我们将通过研究现代Java EE容器实现例如JBoss AS 7.1.2中的不同Map实现来结束本文。 您可以从github master分支获取最新的源代码。 在报告下方找到 JBoss AS7.1.2 Java文件总数2012年8月28日快照7302 使用java.util.Hashtable的Java类总数72 使用java.util.HashMap的Java类总数512 使用同步的HashMap的Java类总数18 使用ConcurrentHashMap的Java类总数46 哈希表引用主要在测试套件组件中以及命名和与JNDI相关的实现中找到。 这种低使用率在这里不足为奇。 从512个Java类中找到了对java.util.HashMap的引用。 考虑到自从最近几年以来这种实现方式的普及程度这再次不足为奇。 但是重要的是要提到从局部变量未在线程间共享同步的HashMap或手动同步防护措施中找到了很好的比率因此“技术上”使线程安全并且不会暴露于上述无限循环条件待处理/隐藏的错误考虑到Java并发编程的复杂性这仍然是一个现实……涉及Oracle Service Bus 11g的案例研究就是一个很好的例子。 发现JMSEJB3RMI和集群等软件包中只有18个Java类使用的同步HashMap使用率较低。 最后在下面找到ConcurrentHashMap用法的细分这是我们主要的兴趣所在。 正如您将在下面看到的那样关键的JBoss组件层例如Web容器EJB3实现等使用此Map实现。 ## JBoss单点登录 用于管理涉及并发线程访问的内部SSO ID 合计1 ## JBoss Java EE和Web容器 这并不奇怪因为许多内部Map数据结构用于管理http会话对象 部署注册表群集和复制统计信息等并发线程访问量大。 总数11 ## JBoss JNDI和安全层 由高度并发的结构例如内部JNDI安全管理使用。 合计4 ## JBoss域和受管服务器管理推出计划… 合计7 ## JBoss EJB3 由数据结构使用例如文件计时器持久性存储应用程序异常实体Bean缓存序列化钝化… 合计8 ## JBoss内核线程池和协议管理 由高并发线程数映射数据结构使用这些数据结构涉及处理和分派/处理传入请求例如HTTP。 合计3 ## JBoss连接器例如JDBC / XA DataSources… 合计2 ## WeldJSR-299的参考实现JavaTM EE平台的上下文和依赖注入用于ClassLoader和涉及并发线程访问的并发静态Map数据结构的上下文。 合计3 ## JBoss测试套件用于某些集成测试用例例如内部数据存储ClassLoader测试等。 合计3 最后的话 我希望本文能帮助您重新研究这个经典问题并理解与错误使用非线程安全HashMap实现有关的常见问题和风险之一。 我的主要建议是在并发线程上下文中使用HashMap时要小心。 除非您是Java并发专家否则我建议您改用ConcurrentHashMap它在性能和线程安全性之间提供了很好的平衡。 像往常一样总是建议进行额外的尽职调查例如执行负载和性能测试周期。 这将使您能够在将解决方案推广到客户生产环境之前检测线程安全和/或性能问题。 参考 Java 7我们的JCG合作伙伴 Pierre-Hugues Charbonneau的HashMap与ConcurrentHashMap 位于Java EE支持模式和Java教程博客。 翻译自: https://www.javacodegeeks.com/2012/08/java-7-hashmap-vs-concurrenthashmap.html
http://www.pierceye.com/news/412328/

相关文章:

  • 网站加上视频对seo影响wordpress打开xml-rpc
  • 个人网站建设分几个步走单页面网站多少钱
  • 自己做网站详细步骤保定网站建设方案优化
  • 传奇手游网站大全9377公司网站建设安全的风险
  • 昆明建设厅网站企业管理咨询上班好吗
  • 福州做网站销售公司用vs2010做网站的好处
  • 深圳企业建站平台网站备案费一般是多少
  • 郑州哪里有做网站郑州货拉拉
  • 汽车网页制作素材滕州网站搜索引擎优化
  • 网站备案地点郓城做网站
  • 专业的外贸网站建设公司价格网站如何制作浙江
  • 东莞运营推广网站建设费用微信小程序开发需要多少钱?
  • 福州专业网站搭建排名沈阳教做网站
  • 公益网站建设方案代码需求网站
  • php网站开发步骤苏州知名网站制作开发
  • 万网免费建企业网站长春搜索引擎优化
  • 网站如何建设数据库网站制作自己接单
  • 为什么有的网站点不开免费的png素材网
  • 百度多久收录网站整体vi设计公司
  • 卡盟网站怎么做图片大全wordpress企业主题餐饮
  • 网站建设培训公司网站跳出率高
  • 电脑网站手机版怎么做网站建设平台哪个公司好
  • 常州网站制作报价wordpress 主页不显示图片
  • 如何在淘宝上做自己的网站东莞通网上营业厅
  • 北京专业响应式网站建设龙岗品牌网站建设
  • 网站qq联系怎么做莲都区建设分局网站
  • 河南旅游集团 网站建设网络运营与推广
  • 搭建网站要多少钱龙岩融胤网络科技有限公司
  • 网站建设实训报告命名规范深圳外贸网站开发
  • 深圳好看的公司网站做网站 网络科技公司