……天天向上

          好的想法總是無窮無盡

          統(tǒng)計(jì)

          留言簿(1)

          閱讀排行榜

          評(píng)論排行榜

          2012年9月19日 #

          calendar獲取當(dāng)前日期及時(shí)間的用例

          1. import Java.util.*;
          2.   public class ShowDate {
          3.   public static void main(String[] args) {
          4.   Calendar calendar = new GregorianCalendar();
          5.   Date trialTime = new Date();
          6.   calendar.setTime(trialTime);
          7.   // print out a bunch of interesting things
          8.   System.out.println("ERA: " + calendar.get(Calendar.ERA));
          9.   System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
          10.   System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
          11.   System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
          12.   System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
          13.   System.out.println("DATE: " + calendar.get(Calendar.DATE));
          14.   System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
          15.   System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
          16.   System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
          17.   System.out.println("DAY_OF_WEEK_IN_MONTH: " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
          18.   System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
          19.   System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
          20.   System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
          21.   System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
          22.   System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
          23.   System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
          24.   System.out.println("ZONE_OFFSET: " + (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
          25.   System.out.println("DST_OFFSET: " + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000)));
          26.   System.out.println("Current Time, with hour reset to 3");
          27.   calendar.clear(Calendar.HOUR_OF_DAY); // so doesn't override
          28.   calendar.set(Calendar.HOUR, 3);
          29.   System.out.println("ERA: " + calendar.get(Calendar.ERA));
          30.   System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
          31.   System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
          32.   System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
          33.   System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
          34.   System.out.println("DATE: " + calendar.get(Calendar.DATE));
          35.   System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
          36.   System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
          37.   System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
          38.   System.out.println("DAY_OF_WEEK_IN_MONTH: " + calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));

          posted @ 2012-09-19 09:51 japper 閱讀(6354) | 評(píng)論 (0)編輯 收藏

          2012年9月10日 #

          Android SDK下載和更新失敗的解決方法


          Android SDK下載和更新失敗的解決方法

           

          最近剛換了電腦,開始搭建Android開發(fā)環(huán)境的時(shí)候,下載SDK總是會(huì)出現(xiàn)如下錯(cuò)誤:
           
          1.Failed to fetch URL http://dl-ssl.google.com/Android/repository/addons_list-1.xml
          據(jù)說dl-ssl.google.com在大陸被強(qiáng)了,偉大的天朝真是不讓人活了,解決方法就是修改C:\Windows\System32\drivers\etc\hosts文件。添加一行:
           
          1.74.125.237.1       dl-ssl.google.com 
          這里需要注意的是hosts文件是只讀的,我們沒有權(quán)限修改,需要我們將hosts文件復(fù)制到桌面或者其他地方,然后修改,代碼如下:
          1.# Copyright (c) 1993-2009 Microsoft Corp. 
          2.# 
          3.# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. 
          4.# 
          5.# This file contains the mappings of IP addresses to host names. Each 
          6.# entry should be kept on an individual line. The IP address should 
          7.# be placed in the first column followed by the corresponding host name. 
          8.# The IP address and the host name should be separated by at least one 
          9.# space. 
          10.# 
          11.# Additionally, comments (such as these) may be inserted on individual 
          12.# lines or following the machine name denoted by a '#' symbol. 
          13.# 
          14.# For example: 
          15.# 
          16.#      102.54.94.97     rhino.acme.com          # source server 
          17.#       38.25.63.10     x.acme.com              # x client host 
          18. 
          19.# localhost name resolution is handled within DNS itself. 
          20.#   127.0.0.1       localhost 
          21.#   ::1             localhost 
          22.//親,就是增加這一句哦  
          23.74.125.237.1       dl-ssl.google.com 
          然后保存,復(fù)制修改后的hosts文件到C:\Windows\System32\drivers\etc 目錄,替換文件就好!!!我們?cè)俅蜗螺dSDK的時(shí)候就會(huì)成功啦,如下圖:
           


          嘿嘿,大功告成啦!!!
           
          PS:補(bǔ)充下,在mac或Linux中,hosts文件所在位置為/etc/hosts,可以使用sudo vim /etc/hosts來編輯。

          posted @ 2012-09-10 11:18 japper 閱讀(349) | 評(píng)論 (0)編輯 收藏

          2012年9月5日 #

          免安裝版Tomcat 6.0.35碰到的問題 :打開tomcat管理界面時(shí),用戶名和密碼錯(cuò)誤的設(shè)置方法

          Tomcat 6.0.35 的功能有些不同于Tomcat 6.0.20。我下載的Tomcat 6.0.35是免安裝的,而以前使用的Tomcat 6.0.20是需要安裝的,而且Tomcat 6.0.20 的安裝密碼,即進(jìn)入Tomcat Manager 這個(gè)地方的密碼是在安裝的時(shí)候指定的,但是呢,Tomcat 6.0.35 由于是免安裝的,所以就沒有地方去指定密碼了,當(dāng)我們?cè)L問Tomcat 6.0.35 的Tomcat Manager的時(shí)候 ,輸入以前默認(rèn)的用戶名:admin 密碼為空,會(huì)發(fā)現(xiàn)出現(xiàn)了403 錯(cuò)誤,即access deny 。調(diào)試了好久,最后終于找出原因了。根據(jù)403頁面的提示,需要在tomcat的配置文件中(即conf/tomcat-users.xml)加入

          <role rolename="manager-gui"/>

          <user username="admin" password="" roles="manager-gui"/>

          有一點(diǎn)必須注意,其中的rolename 必須是“manager-gui” ,更改成admin 或者 admin-gui,都不好用,而下面的username  password是可以任意的,但是后面的roles 必須和上面role 中的rolename相同。

          posted @ 2012-09-05 14:22 japper 閱讀(3835) | 評(píng)論 (0)編輯 收藏

          通過 jconsole查看tomcat運(yùn)行情況的配置方法

          通過 jconsole查看tomcat運(yùn)行情況的配置方法

          ——基于JDK1.5LinuxRedhat5.5)、Tomcat6

          由于項(xiàng)目的原因,需要使用jconsole對(duì)tomcat進(jìn)行遠(yuǎn)程監(jiān)控,結(jié)合網(wǎng)上的資料對(duì)配置方法進(jìn)行了總結(jié)。

          第一步、配置tomcat

          打開%TOMCAT_HOME%/bin下的文件catalina.sh搜索“JAVA_OPTS”找到下面這行:

          if [ -z "$LOGGING_MANAGER" ]; then

            JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"

          else

            JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER"

          fi 

          在每個(gè)“JAVA_OPTS”后邊都添加以下標(biāo)黃代碼段,且在一行顯示

          if [ -z "$LOGGING_MANAGER" ]; then

            JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.rmi.server.hostname=192.9.100.48  -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false""

          else 

            JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER -Djava.rmi.server.hostname=192.9.100.48  -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port="9004" -Dcom.sun.management.jmxremote.authenticate="false" -Dcom.sun.management.jmxremote.ssl="false""

          fi

          其中-Djava.rmi.server.hostname項(xiàng)必須設(shè)置,否則遠(yuǎn)程連接會(huì)因?yàn)榻馕龅?/font>127.0.0.1失敗,該項(xiàng)的值就是你在windows客戶端連接linux時(shí)的ip地址

          -Dcom.sun.management.jmxremote.port="9004"項(xiàng)設(shè)置遠(yuǎn)程連接端口,不要與其他應(yīng)用沖突

          sslauthenticate設(shè)置為false,如果需要安全,請(qǐng)不要false

          、重啟tomcat

          使用root身份登錄系統(tǒng),進(jìn)入%TOMCAT_HOME%/bin目錄下:

          [root@test ~]#ps ef |grep tomcat -輸入命令查看是否存在tomcat進(jìn)程

          [root@test ~]#./shutdown.sh--停止tomcat服務(wù),如果無效使用kill命令殺掉進(jìn)程

          [root@test ~]#./startup.sh  --啟動(dòng)tomcat服務(wù)

          、運(yùn)行jconsole

          進(jìn)入JDK安裝目錄%JDK_HOME%/bin下,找到“jconsole.exe”,點(diǎn)擊運(yùn)行并選擇【遠(yuǎn)程】選項(xiàng)卡:

          在【主機(jī)名或ip】輸入要遠(yuǎn)程監(jiān)控的tomcat服務(wù)器地址

          在【端口】輸入上文設(shè)置的端口號(hào):9004

          【用戶名、口令】為空,點(diǎn)擊【連接】進(jìn)入監(jiān)控界面。

          posted @ 2012-09-05 14:16 japper 閱讀(3959) | 評(píng)論 (0)編輯 收藏

          TOMCAT獲取信息:JMXServiceURL 、JMXConnector 和MBeanServerConnection

          1. import java.lang.management.MemoryUsage;
          2. import java.text.SimpleDateFormat;
          3. import java.util.Date;
          4. import java.util.Formatter;
          5. import java.util.HashMap;
          6. import java.util.Iterator;
          7. import java.util.Map;
          8. import java.util.Set;
          9. import javax.management.MBeanAttributeInfo;
          10. import javax.management.MBeanInfo;
          11. import javax.management.MBeanServerConnection;
          12. import javax.management.ObjectInstance;
          13. import javax.management.ObjectName;
          14. import javax.management.openmbean.CompositeDataSupport;
          15. import javax.management.remote.JMXConnector;
          16. import javax.management.remote.JMXConnectorFactory;
          17. import javax.management.remote.JMXServiceURL;
          18. public class test {
          19. /**
          20. * @param args
          21. */
          22. public static void main(String[] args) {
          23. try {
          24. String jmxURL = "service:jmx:rmi:///jndi/rmi://192.168.1.126:10090/jmxrmi";//tomcat jmx url
          25. JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
          26. Map map = new HashMap();
          27. String[] credentials = new String[] { "monitorRole", "QED" };
          28. map.put("jmx.remote.credentials", credentials);
          29. JMXConnector connector = JMXConnectorFactory.connect(serviceURL, map);
          30. MBeanServerConnection mbsc = connector.getMBeanServerConnection();
          31. //端口最好是動(dòng)態(tài)取得
          32. ObjectName threadObjName = new ObjectName("Catalina:type=ThreadPool,name=http-8089");
          33. MBeanInfo mbInfo = mbsc.getMBeanInfo(threadObjName);
          34. String attrName = "currentThreadCount";//tomcat的線程數(shù)對(duì)應(yīng)的屬性值
          35. MBeanAttributeInfo[] mbAttributes = mbInfo.getAttributes();
          36. System.out.println("currentThreadCount:" + mbsc.getAttribute(threadObjName, attrName));
          37. //heap
          38. for (int j = 0; j < mbsc.getDomains().length; j++) {
          39. System.out.println("###########" + mbsc.getDomains()[j]);
          40. }
          41. Set MBeanset = mbsc.queryMBeans(null, null);
          42. System.out.println("MBeanset.size() : " + MBeanset.size());
          43. Iterator MBeansetIterator = MBeanset.iterator();
          44. while (MBeansetIterator.hasNext()) {
          45. ObjectInstance objectInstance = (ObjectInstance) MBeansetIterator.next();
          46. ObjectName objectName = objectInstance.getObjectName();
          47. String canonicalName = objectName.getCanonicalName();
          48. System.out.println("canonicalName : " + canonicalName);
          49. if (canonicalName.equals("Catalina:host=localhost,type=Cluster")) {
          50. // Get details of cluster MBeans
          51. System.out.println("Cluster MBeans Details:");
          52. System.out.println("=========================================");
          53. //getMBeansDetails(canonicalName);
          54. String canonicalKeyPropList = objectName.getCanonicalKeyPropertyListString();
          55. }
          56. }
          57. //------------------------- system ----------------------
          58. ObjectName runtimeObjName = new ObjectName("java.lang:type=Runtime");
          59. System.out.println("廠商:" + (String) mbsc.getAttribute(runtimeObjName, "VmVendor"));
          60. System.out.println("程序:" + (String) mbsc.getAttribute(runtimeObjName, "VmName"));
          61. System.out.println("版本:" + (String) mbsc.getAttribute(runtimeObjName, "VmVersion"));
          62. Date starttime = new Date((Long) mbsc.getAttribute(runtimeObjName, "StartTime"));
          63. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          64. System.out.println("啟動(dòng)時(shí)間:" + df.format(starttime));
          65. Long timespan = (Long) mbsc.getAttribute(runtimeObjName, "Uptime");
          66. System.out.println("連續(xù)工作時(shí)間:" + test.formatTimeSpan(timespan));
          67. //------------------------ JVM -------------------------
          68. //堆使用率
          69. ObjectName heapObjName = new ObjectName("java.lang:type=Memory");
          70. MemoryUsage heapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,
          71. "HeapMemoryUsage"));
          72. long maxMemory = heapMemoryUsage.getMax();//堆最大
          73. long commitMemory = heapMemoryUsage.getCommitted();//堆當(dāng)前分配
          74. long usedMemory = heapMemoryUsage.getUsed();
          75. System.out.println("heap:" + (double) usedMemory * 100 / commitMemory + "%");//堆使用率
          76. MemoryUsage nonheapMemoryUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(heapObjName,
          77. "NonHeapMemoryUsage"));
          78. long noncommitMemory = nonheapMemoryUsage.getCommitted();
          79. long nonusedMemory = heapMemoryUsage.getUsed();
          80. System.out.println("nonheap:" + (double) nonusedMemory * 100 / noncommitMemory + "%");
          81. ObjectName permObjName = new ObjectName("java.lang:type=MemoryPool,name=Perm Gen");
          82. MemoryUsage permGenUsage = MemoryUsage.from((CompositeDataSupport) mbsc.getAttribute(permObjName, "Usage"));
          83. long committed = permGenUsage.getCommitted();//持久堆大小
          84. long used = heapMemoryUsage.getUsed();//
          85. System.out.println("perm gen:" + (double) used * 100 / committed + "%");//持久堆使用率
          86. //-------------------- Session ---------------
          87. ObjectName managerObjName = new ObjectName("Catalina:type=Manager,*");
          88. Set<ObjectName> s = mbsc.queryNames(managerObjName, null);
          89. for (ObjectName obj : s) {
          90. System.out.println("應(yīng)用名:" + obj.getKeyProperty("path"));
          91. ObjectName objname = new ObjectName(obj.getCanonicalName());
          92. System.out.println("最大會(huì)話數(shù):" + mbsc.getAttribute(objname, "maxActiveSessions"));
          93. System.out.println("會(huì)話數(shù):" + mbsc.getAttribute(objname, "activeSessions"));
          94. System.out.println("活動(dòng)會(huì)話數(shù):" + mbsc.getAttribute(objname, "sessionCounter"));
          95. }
          96. //----------------- Thread Pool ----------------
          97. ObjectName threadpoolObjName = new ObjectName("Catalina:type=ThreadPool,*");
          98. Set<ObjectName> s2 = mbsc.queryNames(threadpoolObjName, null);
          99. for (ObjectName obj : s2) {
          100. System.out.println("端口名:" + obj.getKeyProperty("name"));
          101. ObjectName objname = new ObjectName(obj.getCanonicalName());
          102. System.out.println("最大線程數(shù):" + mbsc.getAttribute(objname, "maxThreads"));
          103. System.out.println("當(dāng)前線程數(shù):" + mbsc.getAttribute(objname, "currentThreadCount"));
          104. System.out.println("繁忙線程數(shù):" + mbsc.getAttribute(objname, "currentThreadsBusy"));
          105. }
          106. } catch (Exception e) {
          107. e.printStackTrace();
          108. }
          109. }
          110. public static String formatTimeSpan(long span) {
          111. long minseconds = span % 1000;
          112. span = span / 1000;
          113. long seconds = span % 60;
          114. span = span / 60;
          115. long mins = span % 60;
          116. span = span / 60;
          117. long hours = span % 24;
          118. span = span / 24;
          119. long days = span;
          120. return (new Formatter()).format("%1$d天 %2$02d:%3$02d:%4$02d.%5$03d", days, hours, mins, seconds, minseconds)
          121. .toString();
          122. }
          123. }

          1. import java.util.Iterator;
          2. import java.util.Set;
          3. import javax.management.Attribute;
          4. import javax.management.MBeanInfo;
          5. import javax.management.MBeanServerConnection;
          6. import javax.management.MBeanServerInvocationHandler;
          7. import javax.management.ObjectInstance;
          8. import javax.management.ObjectName;
          9. import javax.management.remote.JMXConnector;
          10. import javax.management.remote.JMXConnectorFactory;
          11. import javax.management.remote.JMXServiceURL;
          12. public class Client {
          13. public static void main(String[] args) throws Exception {
          14. JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/server");
          15. JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
          16. MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
          17. ObjectName mbeanName = new ObjectName("chengang:name=HelloWorld");
          18. // 把所有Domain都打印出來
          19. System.out.println("Domains:---------------");
          20. String domains[] = mbsc.getDomains();
          21. for (int i = 0; i < domains.length; i++) {
          22. System.out.println("\tDomain[" + i + "] = " + domains[i]);
          23. }
          24. // MBean的總數(shù)
          25. System.out.println("MBean count = " + mbsc.getMBeanCount());
          26. // 對(duì)name屬性的操作(屬性名的第一個(gè)字母要大寫)
          27. mbsc.setAttribute(mbeanName, new Attribute("Name", "PANDA"));// 設(shè)值
          28. System.out.println("Name = " + mbsc.getAttribute(mbeanName, "Name"));// 取值
          29. // 得到proxy代理后直接調(diào)用的方式
          30. HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);
          31. proxy.printHello();
          32. proxy.printHello("Raymend");
          33. // 遠(yuǎn)程調(diào)用的方式
          34. mbsc.invoke(mbeanName, "printHello", null, null);
          35. mbsc.invoke(mbeanName, "printHello", new Object[] { "熊貓燒香" }, new String[] { String.class.getName() });
          36. // 得mbean的信息
          37. MBeanInfo info = mbsc.getMBeanInfo(mbeanName);
          38. System.out.println("Hello Class: " + info.getClassName());
          39. System.out.println("Hello Attriber:" + info.getAttributes()[0].getName());
          40. System.out.println("Hello Operation:" + info.getOperations()[0].getName());
          41. // 得到所有的MBean的ObjectName
          42. System.out.println("all ObjectName:---------------");
          43. Set set = mbsc.queryMBeans(null, null);
          44. for (Iterator it = set.iterator(); it.hasNext();) {
          45. ObjectInstance oi = (ObjectInstance) it.next();
          46. System.out.println("\t" + oi.getObjectName());
          47. }
          48. // 關(guān)閉MBeanServer連接
          49. jmxc.close();
          50. }
          51. }

          posted @ 2012-09-05 14:14 japper 閱讀(4994) | 評(píng)論 (0)編輯 收藏

          LinkedHashMap和HashMap的比較使用

          由于現(xiàn)在項(xiàng)目中用到了LinkedHashMap,并不是太熟悉就到網(wǎng)上搜了一下。







          import
          java.util.HashMap;

          import
          java.util.Iterator;

          import
          java.util.LinkedHashMap;

          import
          java.util.Map;

          public
          class TestLinkedHashMap {


            public static
          void main(String
          args[])

            {

             System.out.println("*************************LinkedHashMap*************");

             Map<Integer,String> map = new LinkedHashMap<Integer,String>();

             map.put(6, "apple");

             map.put(3, "banana");

             map.put(2,"pear");

            

             for (Iterator it =  map.keySet().iterator();it.hasNext();)

             {

              Object key = it.next();

              System.out.println(
          key+
          "="+
          map.get(key));

             }

            

             System.out.println("*************************HashMap*************");

             Map<Integer,String>
          map1 =
          new  HashMap<Integer,String>();

             map1.put(6, "apple");

             map1.put(3, "banana");

             map1.put(2,"pear");

            

             for (Iterator it = map1.keySet().iterator();it.hasNext();)

             {

              Object key = it.next();

              System.out.println(
          key+
          "="+
          map1.get(key));

             }

            }

          }


          運(yùn)行結(jié)果如下:


          *************************LinkedHashMap*************
          6=apple
          3=banana
          2=pear
          *************************HashMap**************************
          2=pear
          6=apple
          3=banana


          分析:LinkedHashmap 的特點(diǎn)是put進(jìn)去的對(duì)象位置未發(fā)生變化,而HashMap會(huì)發(fā)生變化.


          再普及下:




          java為數(shù)據(jù)結(jié)構(gòu)中的映射定義了一個(gè)接口java.util.Map;它有四個(gè)實(shí)現(xiàn)類,分別是HashMap
          Hashtable LinkedHashMap 和TreeMap
          .


          Map主要用于存儲(chǔ)健值對(duì),根據(jù)鍵得到值,因此不允許鍵重復(fù)(重復(fù)了覆蓋了),但允許值重復(fù)。
          Hashmap
          是一個(gè)最常用的Map,它根據(jù)鍵的HashCode值存儲(chǔ)數(shù)據(jù),根據(jù)鍵可以直接獲取它的值,具有很快的訪問速度,遍歷時(shí),取得數(shù)據(jù)的順序是完全隨機(jī)的。
          HashMap最多只允許一條記錄的鍵為Null;允許多條記錄的值為
          Null;HashMap不支持線程的同步,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫HashMap;可能會(huì)導(dǎo)致數(shù)據(jù)的不一致。如果需要同步,可以用
          Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。


          Hashtable與
          HashMap類似,它繼承自Dictionary類,不同的是:它不允許記錄的鍵或者值為空;它支持線程的同步,即任一時(shí)刻只有一個(gè)線程能寫Hashtable,因此也導(dǎo)致了
          Hashtable在寫入時(shí)會(huì)比較慢。


          LinkedHashMap
          是HashMap的一個(gè)子類,保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的.也可以在構(gòu)造時(shí)用帶參數(shù),按照應(yīng)用次數(shù)排序。在遍歷的時(shí)候會(huì)比HashMap慢,不過有種情況例外,當(dāng)HashMap容量很大,實(shí)際數(shù)據(jù)較少時(shí),遍歷起來可能會(huì)比
          LinkedHashMap慢,因?yàn)長(zhǎng)inkedHashMap的遍歷速度只和實(shí)際數(shù)據(jù)有關(guān),和容量無關(guān),而HashMap的遍歷速度和他的容量有關(guān)。


          TreeMap實(shí)現(xiàn)SortMap接口,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序,也可以指定排序的比較器,當(dāng)用Iterator
          遍歷TreeMap時(shí),得到的記錄是排過序的。


          一般情況下,我們用的最多的是HashMap,在Map 中插入、刪除和定位元素,HashMap
          是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會(huì)更好。如果需要輸出的順序和輸入的相同,那么用LinkedHashMap
          可以實(shí)現(xiàn),它還可以按讀取順序來排列.


          HashMap是一個(gè)最常用的Map,它根據(jù)鍵的hashCode值存儲(chǔ)數(shù)據(jù),根據(jù)鍵可以直接獲取它的值,具有很快的訪問速度。HashMap最多只允許一條記錄的鍵為NULL,允許多條記錄的值為NULL。


          HashMap不支持線程同步,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫HashMap,可能會(huì)導(dǎo)致數(shù)據(jù)的不一致性。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。


          Hashtable與HashMap類似,不同的是:它不允許記錄的鍵或者值為空;它支持線程的同步,即任一時(shí)刻只有一個(gè)線程能寫Hashtable,因此也導(dǎo)致了Hashtable在寫入時(shí)會(huì)比較慢。


          LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的。


          在遍歷的時(shí)候會(huì)比HashMap慢TreeMap能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按升序排序,也可以指定排序的比較器。當(dāng)用Iterator遍歷TreeMap時(shí),得到的記錄是排過序的。

          posted @ 2012-09-05 14:12 japper 閱讀(16471) | 評(píng)論 (5)編輯 收藏

          2012年8月29日 #

          java synchronized詳解 (轉(zhuǎn))

          記下來,很重要。

          Java語言的關(guān)鍵字,當(dāng)它用來修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。

               一、當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。

               二、然而,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

               三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

               四、第三個(gè)例子同樣適用其它同步代碼塊。也就是說,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問都被暫時(shí)阻塞。

               五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用.

          舉例說明: 
               一、當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。

          package ths;

          public class Thread1 implements Runnable { 
               public void run() { 
                    synchronized(this) { 
                         for (int i = 0; i < 5; i++) { 
                              System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); 
                         } 
                    } 
               } 
               public static void main(String[] args) { 
                    Thread1 t1 = new Thread1(); 
                    Thread ta = new Thread(t1, "A"); 
                    Thread tb = new Thread(t1, "B"); 
                    ta.start(); 
                    tb.start(); 
               }    
          }

          結(jié)果: 
               A synchronized loop 0 
               A synchronized loop 1 
               A synchronized loop 2 
               A synchronized loop 3 
               A synchronized loop 4 
               B synchronized loop 0 
               B synchronized loop 1 
               B synchronized loop 2 
               B synchronized loop 3 
               B synchronized loop 4

               二、然而,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

          package ths;

          public class Thread2 { 
               public void m4t1() { 
                    synchronized(this) { 
                         int i = 5; 
                         while( i-- > 0) { 
                              System.out.println(Thread.currentThread().getName() + " : " + i); 
                              try { 
                                   Thread.sleep(500); 
                              } catch (InterruptedException ie) { 
                              } 
                         } 
                    } 
               } 
               public void m4t2() { 
                    int i = 5; 
                    while( i-- > 0) { 
                         System.out.println(Thread.currentThread().getName() + " : " + i); 
                         try { 
                              Thread.sleep(500); 
                         } catch (InterruptedException ie) { 
                         } 
                    } 
               } 
               public static void main(String[] args) { 
                    final Thread2 myt2 = new Thread2(); 
                    Thread t1 = new Thread(  new Runnable() {  public void run() {  myt2.m4t1();  }  }, "t1"  ); 
                    Thread t2 = new Thread(  new Runnable() {  public void run() { myt2.m4t2();   }  }, "t2"  ); 
                    t1.start(); 
                    t2.start(); 
               }    
          }

          結(jié)果: 
               t1 : 4 
               t2 : 4 
               t1 : 3 
               t2 : 3 
               t1 : 2 
               t2 : 2 
               t1 : 1 
               t2 : 1 
               t1 : 0 
               t2 : 0

               三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

               //修改Thread2.m4t2()方法: 
               public void m4t2() { 
                    synchronized(this) { 
                         int i = 5; 
                         while( i-- > 0) { 
                              System.out.println(Thread.currentThread().getName() + " : " + i); 
                              try { 
                                   Thread.sleep(500); 
                              } catch (InterruptedException ie) { 
                              } 
                         } 
                    }

               }

          結(jié)果:

               t1 : 4 
               t1 : 3 
               t1 : 2 
               t1 : 1 
               t1 : 0 
               t2 : 4 
               t2 : 3 
               t2 : 2 
               t2 : 1 
               t2 : 0

               四、第三個(gè)例子同樣適用其它同步代碼塊。也就是說,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問都被暫時(shí)阻塞。

               //修改Thread2.m4t2()方法如下:

               public synchronized void m4t2() { 
                    int i = 5; 
                    while( i-- > 0) { 
                         System.out.println(Thread.currentThread().getName() + " : " + i); 
                         try { 
                              Thread.sleep(500); 
                         } catch (InterruptedException ie) { 
                         } 
                    } 
               }

          結(jié)果: 
               t1 : 4 
               t1 : 3 
               t1 : 2 
               t1 : 1 
               t1 : 0 
               t2 : 4 
               t2 : 3 
               t2 : 2 
               t2 : 1 
               t2 : 0

               五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用:

          package ths;

          public class Thread3 {   
               class Inner {    
                    private void m4t1() {    
                         int i = 5;    
                         while(i-- > 0) {    
                              System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + i);    
                              try {    
                                   Thread.sleep(500);    
                              } catch(InterruptedException ie) {    
                              }    
                         }    
                    }    
                    private void m4t2() {    
                         int i = 5;    
                         while(i-- > 0) {    
                              System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i);    
                              try {    
                                   Thread.sleep(500);    
                              } catch(InterruptedException ie) {    
                              }    
                         }    
                    }    
               }    
               private void m4t1(Inner inner) {    
                    synchronized(inner) { //使用對(duì)象鎖    
                    inner.m4t1();    
               }    
               private void m4t2(Inner inner) {    
                    inner.m4t2();    
               }    
               public static void main(String[] args) {    
                    final Thread3 myt3 = new Thread3();    
                    final Inner inner = myt3.new Inner();    
                    Thread t1 = new Thread( new Runnable() {public void run() { myt3.m4t1(inner);} }, "t1");    
               Thread t2 = new Thread( new Runnable() {public void run() { myt3.m4t2(inner);} }, "t2");    
               t1.start();    
               t2.start();    
            }    
          }

          結(jié)果:

          盡管線程t1獲得了對(duì)Inner的對(duì)象鎖,但由于線程t2訪問的是同一個(gè)Inner中的非同步部分。所以兩個(gè)線程互不干擾。

               t1 : Inner.m4t1()=4 
               t2 : Inner.m4t2()=4 
               t1 : Inner.m4t1()=3 
               t2 : Inner.m4t2()=3 
               t1 : Inner.m4t1()=2 
               t2 : Inner.m4t2()=2 
               t1 : Inner.m4t1()=1 
               t2 : Inner.m4t2()=1 
               t1 : Inner.m4t1()=0 
               t2 : Inner.m4t2()=0

          現(xiàn)在在Inner.m4t2()前面加上synchronized:

               private synchronized void m4t2() { 
                    int i = 5; 
                    while(i-- > 0) { 
                         System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + i); 
                         try { 
                              Thread.sleep(500); 
                         } catch(InterruptedException ie) { 
                         } 
                    } 
               }

          結(jié)果:

          盡管線程t1與t2訪問了同一個(gè)Inner對(duì)象中兩個(gè)毫不相關(guān)的部分,但因?yàn)閠1先獲得了對(duì)Inner的對(duì)象鎖,所以t2對(duì)Inner.m4t2()的訪問也被阻塞,因?yàn)閙4t2()是Inner中的一個(gè)同步方法。

               t1 : Inner.m4t1()=4 
               t1 : Inner.m4t1()=3 
               t1 : Inner.m4t1()=2 
               t1 : Inner.m4t1()=1 
               t1 : Inner.m4t1()=0 
               t2 : Inner.m4t2()=4 
               t2 : Inner.m4t2()=3 
               t2 : Inner.m4t2()=2 
               t2 : Inner.m4t2()=1 
               t2 : Inner.m4t2()=0

          第二篇:

          synchronized 關(guān)鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。 
          1. synchronized 方法:通過在方法聲明中加入 synchronized關(guān)鍵字來聲明 synchronized 方法。如: 
          public synchronized void accessVal(int newVal); 
          synchronized 方法控制對(duì)類成員變量的訪問:每個(gè)類實(shí)例對(duì)應(yīng)一把鎖,每個(gè) synchronized 方法都必須獲得調(diào)用該方法的類實(shí)例的鎖方能

          執(zhí)行,否則所屬線程阻塞,方法一旦執(zhí)行,就獨(dú)占該鎖,直到從該方法返回時(shí)才將鎖釋放,此后被阻塞的線程方能獲得該鎖,重新進(jìn)入可執(zhí)行

          狀態(tài)。這種機(jī)制確保了同一時(shí)刻對(duì)于每一個(gè)類實(shí)例,其所有聲明為 synchronized 的成員函數(shù)中至多只有一個(gè)處于可執(zhí)行狀態(tài)(因?yàn)橹炼嘀挥?/p>

          一個(gè)能夠獲得該類實(shí)例對(duì)應(yīng)的鎖),從而有效避免了類成員變量的訪問沖突(只要所有可能訪問類成員變量的方法均被聲明為 synchronized)

          。 
          在 Java 中,不光是類實(shí)例,每一個(gè)類也對(duì)應(yīng)一把鎖,這樣我們也可將類的靜態(tài)成員函數(shù)聲明為 synchronized ,以控制其對(duì)類的靜態(tài)成

          員變量的訪問。 
          synchronized 方法的缺陷:若將一個(gè)大的方法聲明為synchronized 將會(huì)大大影響效率,典型地,若將線程類的方法 run() 聲明為

          synchronized ,由于在線程的整個(gè)生命期內(nèi)它一直在運(yùn)行,因此將導(dǎo)致它對(duì)本類任何 synchronized 方法的調(diào)用都永遠(yuǎn)不會(huì)成功。當(dāng)然我們可

          以通過將訪問類成員變量的代碼放到專門的方法中,將其聲明為 synchronized ,并在主方法中調(diào)用來解決這一問題,但是 Java 為我們提供

          了更好的解決辦法,那就是 synchronized 塊。 
          2. synchronized 塊:通過 synchronized關(guān)鍵字來聲明synchronized 塊。語法如下: 
          synchronized(syncObject) { 
          //允許訪問控制的代碼 

          synchronized 塊是這樣一個(gè)代碼塊,其中的代碼必須獲得對(duì)象 syncObject (如前所述,可以是類實(shí)例或類)的鎖方能執(zhí)行,具體機(jī)

          制同前所述。由于可以針對(duì)任意代碼塊,且可任意指定上鎖的對(duì)象,故靈活性較高。 
          對(duì)synchronized(this)的一些理解    
          一、當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線

          程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。 
          二、然而,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問該object中的非synchronized

          (this)同步代碼塊。 
          三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)

          同步代碼塊的訪問將被阻塞。 
          四、第三個(gè)例子同樣適用其它同步代碼塊。也就是說,當(dāng)一個(gè)線程訪問object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)

          object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問都被暫時(shí)阻塞。 
          五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用

          http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html
          java中synchronized用法

          打個(gè)比方:一個(gè)object就像一個(gè)大房子,大門永遠(yuǎn)打開。房子里有 很多房間(也就是方法)。

          這些房間有上鎖的(synchronized方法), 和不上鎖之分(普通方法)。房門口放著一把鑰匙(key),這把鑰匙可以打開所有上鎖的房間。

          另外我把所有想調(diào)用該對(duì)象方法的線程比喻成想進(jìn)入這房子某個(gè) 房間的人。所有的東西就這么多了,下面我們看看這些東西之間如何作用的。

          在此我們先來明確一下我們的前提條件。該對(duì)象至少有一個(gè)synchronized方法,否則這個(gè)key還有啥意義。當(dāng)然也就不會(huì)有我們的這個(gè)主題了。

          一個(gè)人想進(jìn)入某間上了鎖的房間,他來到房子門口,看見鑰匙在那兒(說明暫時(shí)還沒有其他人要使用上鎖的 房間)。于是他走上去拿到了鑰匙

          ,并且按照自己 的計(jì)劃使用那些房間。注意一點(diǎn),他每次使用完一次上鎖的房間后會(huì)馬上把鑰匙還回去。即使他要連續(xù)使用兩間上鎖的房間,

          中間他也要把鑰匙還回去,再取回來。

          因此,普通情況下鑰匙的使用原則是:“隨用隨借,用完即還。”

          這時(shí)其他人可以不受限制的使用那些不上鎖的房間,一個(gè)人用一間可以,兩個(gè)人用一間也可以,沒限制。但是如果當(dāng)某個(gè)人想要進(jìn)入上鎖的房

          間,他就要跑到大門口去看看了。有鑰匙當(dāng)然拿了就走,沒有的話,就只能等了。

          要是很多人在等這把鑰匙,等鑰匙還回來以后,誰會(huì)優(yōu)先得到鑰匙?Not guaranteed。象前面例子里那個(gè)想連續(xù)使用兩個(gè)上鎖房間的家伙,他

          中間還鑰匙的時(shí)候如果還有其他人在等鑰匙,那么沒有任何保證這家伙能再次拿到。 (JAVA規(guī)范在很多地方都明確說明不保證,象

          Thread.sleep()休息后多久會(huì)返回運(yùn)行,相同優(yōu)先權(quán)的線程那個(gè)首先被執(zhí)行,當(dāng)要訪問對(duì)象的鎖被 釋放后處于等待池的多個(gè)線程哪個(gè)會(huì)優(yōu)先得

          到,等等。我想最終的決定權(quán)是在JVM,之所以不保證,就是因?yàn)镴VM在做出上述決定的時(shí)候,絕不是簡(jiǎn)簡(jiǎn)單單根據(jù) 一個(gè)條件來做出判斷,而是

          根據(jù)很多條。而由于判斷條件太多,如果說出來可能會(huì)影響JAVA的推廣,也可能是因?yàn)橹R(shí)產(chǎn)權(quán)保護(hù)的原因吧。SUN給了個(gè)不保證 就混過去了

          。無可厚非。但我相信這些不確定,并非完全不確定。因?yàn)橛?jì)算機(jī)這東西本身就是按指令運(yùn)行的。即使看起來很隨機(jī)的現(xiàn)象,其實(shí)都是有規(guī)律

          可尋。學(xué)過 計(jì)算機(jī)的都知道,計(jì)算機(jī)里隨機(jī)數(shù)的學(xué)名是偽隨機(jī)數(shù),是人運(yùn)用一定的方法寫出來的,看上去隨機(jī)罷了。另外,或許是因?yàn)橐肱?/p>

          的確定太費(fèi)事,也沒多大意義,所 以不確定就不確定了吧。)

          再來看看同步代碼塊。和同步方法有小小的不同。

          1.從尺寸上講,同步代碼塊比同步方法小。你可以把同步代碼塊看成是沒上鎖房間里的一塊用帶鎖的屏風(fēng)隔開的空間。

          2.同步代碼塊還可以人為的指定獲得某個(gè)其它對(duì)象的key。就像是指定用哪一把鑰匙才能開這個(gè)屏風(fēng)的鎖,你可以用本房的鑰匙;你也可以指定

          用另一個(gè)房子的鑰匙才能開,這樣的話,你要跑到另一棟房子那兒把那個(gè)鑰匙拿來,并用那個(gè)房子的鑰匙來打開這個(gè)房子的帶鎖的屏風(fēng)。

                   記住你獲得的那另一棟房子的鑰匙,并不影響其他人進(jìn)入那棟房子沒有鎖的房間。

                   為什么要使用同步代碼塊呢?我想應(yīng)該是這樣的:首先對(duì)程序來講同步的部分很影響運(yùn)行效率,而一個(gè)方法通常是先創(chuàng)建一些局部變

          量,再對(duì)這些變量做一些 操作,如運(yùn)算,顯示等等;而同步所覆蓋的代碼越多,對(duì)效率的影響就越嚴(yán)重。因此我們通常盡量縮小其影響范圍。

          如何做?同步代碼塊。我們只把一個(gè)方法中該同 步的地方同步,比如運(yùn)算。

                   另外,同步代碼塊可以指定鑰匙這一特點(diǎn)有個(gè)額外的好處,是可以在一定時(shí)期內(nèi)霸占某個(gè)對(duì)象的key。還記得前面說過普通情況下鑰

          匙的使用原則嗎。現(xiàn)在不是普通情況了。你所取得的那把鑰匙不是永遠(yuǎn)不還,而是在退出同步代碼塊時(shí)才還。

                    還用前面那個(gè)想連續(xù)用兩個(gè)上鎖房間的家伙打比方。怎樣才能在用完一間以后,繼續(xù)使用另一間呢。用同步代碼塊吧。先創(chuàng)建另外

          一個(gè)線程,做一個(gè)同步代碼 塊,把那個(gè)代碼塊的鎖指向這個(gè)房子的鑰匙。然后啟動(dòng)那個(gè)線程。只要你能在進(jìn)入那個(gè)代碼塊時(shí)抓到這房子的鑰匙

          ,你就可以一直保留到退出那個(gè)代碼塊。也就是說 你甚至可以對(duì)本房?jī)?nèi)所有上鎖的房間遍歷,甚至再sleep(10*60*1000),而房門口卻還有

          1000個(gè)線程在等這把鑰匙呢。很過癮吧。

                    在此對(duì)sleep()方法和鑰匙的關(guān)聯(lián)性講一下。一個(gè)線程在拿到key后,且沒有完成同步的內(nèi)容時(shí),如果被強(qiáng)制sleep()了,那key還一

          直在 它那兒。直到它再次運(yùn)行,做完所有同步內(nèi)容,才會(huì)歸還key。記住,那家伙只是干活干累了,去休息一下,他并沒干完他要干的事。為

          了避免別人進(jìn)入那個(gè)房間 把里面搞的一團(tuán)糟,即使在睡覺的時(shí)候他也要把那唯一的鑰匙戴在身上。

                    最后,也許有人會(huì)問,為什么要一把鑰匙通開,而不是一個(gè)鑰匙一個(gè)門呢?我想這純粹是因?yàn)閺?fù)雜性問題。一個(gè)鑰匙一個(gè)門當(dāng)然更

          安全,但是會(huì)牽扯好多問題。鑰匙 的產(chǎn)生,保管,獲得,歸還等等。其復(fù)雜性有可能隨同步方法的增加呈幾何級(jí)數(shù)增加,嚴(yán)重影響效率。這也

          算是一個(gè)權(quán)衡的問題吧。為了增加一點(diǎn)點(diǎn)安全性,導(dǎo)致效 率大大降低,是多么不可取啊。

          synchronized的一個(gè)簡(jiǎn)單例子

          public class TextThread {

          public static void main(String[] args) {   
             TxtThread tt = new TxtThread();    
             new Thread(tt).start();    
             new Thread(tt).start();    
             new Thread(tt).start();    
             new Thread(tt).start();    
          }    
          }

          class TxtThread implements Runnable {   
          int num = 100;    
          String str = new String();

          public void run() {   
             synchronized (str) {    
              while (num > 0) {

               try {   
                Thread.sleep(1);    
               } catch (Exception e) {    
                e.getMessage();    
               }    
               System.out.println(Thread.currentThread().getName()    
                 + "this is " + num--);    
              }    
             }    
          }    
          }

          上面的例子中為了制造一個(gè)時(shí)間差,也就是出錯(cuò)的機(jī)會(huì),使用了Thread.sleep(10)

          Java對(duì)多線程的支持與同步機(jī)制深受大家的喜愛,似乎看起來使用了synchronized關(guān)鍵字就可以輕松地解決多線程共享數(shù)據(jù)同步問題。到底如

          何?――還得對(duì)synchronized關(guān)鍵字的作用進(jìn)行深入了解才可定論。

          總的說來,synchronized關(guān)鍵字可以作為函數(shù)的修飾符,也可作為函數(shù)內(nèi)的語句,也就是平時(shí)說的同步方法和同步語句塊。如果再細(xì)的分類,

          synchronized可作用于instance變量、object reference(對(duì)象引用)、static函數(shù)和class literals(類名稱字面常量)身上。

          在進(jìn)一步闡述之前,我們需要明確幾點(diǎn):

          A.無論synchronized關(guān)鍵字加在方法上還是對(duì)象上,它取得的鎖都是對(duì)象,而不是把一段代碼或函數(shù)當(dāng)作鎖――而且同步方法很可能還會(huì)被其

          他線程的對(duì)象訪問。

          B.每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián)。

          C.實(shí)現(xiàn)同步是要很大的系統(tǒng)開銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無謂的同步控制。

          接著來討論synchronized用到不同地方對(duì)代碼產(chǎn)生的影響:

          假設(shè)P1、P2是同一個(gè)類的不同對(duì)象,這個(gè)類中定義了以下幾種情況的同步塊或同步方法,P1、P2就都可以調(diào)用它們。

          1. 把synchronized當(dāng)作函數(shù)修飾符時(shí),示例代碼如下:

          Public synchronized void methodAAA()

          {

          //….

          }

          這也就是同步方法,那這時(shí)synchronized鎖定的是哪個(gè)對(duì)象呢?它鎖定的是調(diào)用這個(gè)同步方法對(duì)象。也就是說,當(dāng)一個(gè)對(duì)象P1在不同的線程中

          執(zhí)行這個(gè)同步方法時(shí),它們之間會(huì)形成互斥,達(dá)到同步的效果。但是這個(gè)對(duì)象所屬的Class所產(chǎn)生的另一對(duì)象P2卻可以任意調(diào)用這個(gè)被加了

          synchronized關(guān)鍵字的方法。

          上邊的示例代碼等同于如下代碼:

          public void methodAAA()

          {

          synchronized (this)      // (1)

          {

                 //…..

          }

          }

          (1)處的this指的是什么呢?它指的就是調(diào)用這個(gè)方法的對(duì)象,如P1。可見同步方法實(shí)質(zhì)是將synchronized作用于object reference。――那個(gè)

          拿到了P1對(duì)象鎖的線程,才可以調(diào)用P1的同步方法,而對(duì)P2而言,P1這個(gè)鎖與它毫不相干,程序也可能在這種情形下擺脫同步機(jī)制的控制,造

          成數(shù)據(jù)混亂:(

          2.同步塊,示例代碼如下:

          public void method3(SomeObject so)

          {

              synchronized(so)

              {   
                 //…..    
              }

          }

          這時(shí),鎖就是so這個(gè)對(duì)象,誰拿到這個(gè)鎖誰就可以運(yùn)行它所控制的那段代碼。當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就可以這樣寫程序,但當(dāng)沒有明

          確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),可以創(chuàng)建一個(gè)特殊的instance變量(它得是一個(gè)對(duì)象)來充當(dāng)鎖:

          class Foo implements Runnable

          {

                  private byte[] lock = new byte[0]; // 特殊的instance變量

                  Public void methodA()   
                  {

                     synchronized(lock) { //… }

                  }

                  //…..

          }

          注:零長(zhǎng)度的byte數(shù)組對(duì)象創(chuàng)建起來將比任何對(duì)象都經(jīng)濟(jì)――查看編譯后的字節(jié)碼:生成零長(zhǎng)度的byte[]對(duì)象只需3條操作碼,而Object lock

          = new Object()則需要7行操作碼。

          3.將synchronized作用于static 函數(shù),示例代碼如下:

          Class Foo   
          {

              public synchronized static void methodAAA()   // 同步的static 函數(shù)   
              {    
                  //….    
              }

              public void methodBBB()   
              {

                 synchronized(Foo.class)   // class literal(類名稱字面常量)

              }   
          }

             代碼中的methodBBB()方法是把class literal作為鎖的情況,它和同步的static函數(shù)產(chǎn)生的效果是一樣的,取得的鎖很特別,是當(dāng)前調(diào)用這

          個(gè)方法的對(duì)象所屬的類(Class,而不再是由這個(gè)Class產(chǎn)生的某個(gè)具體對(duì)象了)。

          記得在《Effective Java》一書中看到過將 Foo.class和 P1.getClass()用于作同步鎖還不一樣,不能用P1.getClass()來達(dá)到鎖這個(gè)Class的

          目的。P1指的是由Foo類產(chǎn)生的對(duì)象。

          可以推斷:如果一個(gè)類中定義了一個(gè)synchronized的static函數(shù)A,也定義了一個(gè)synchronized 的instance函數(shù)B,那么這個(gè)類的同一對(duì)象Obj

          在多線程中分別訪問A和B兩個(gè)方法時(shí),不會(huì)構(gòu)成同步,因?yàn)樗鼈兊逆i都不一樣。A方法的鎖是Obj這個(gè)對(duì)象,而B的鎖是Obj所屬的那個(gè)Class。

          小結(jié)如下:

          搞清楚synchronized鎖定的是哪個(gè)對(duì)象,就能幫助我們?cè)O(shè)計(jì)更安全的多線程程序。

          還有一些技巧可以讓我們對(duì)共享資源的同步訪問更加安全:

          1. 定義private 的instance變量+它的 get方法,而不要定義public/protected的instance變量。如果將變量定義為public,對(duì)象在外界可以

          繞過同步方法的控制而直接取得它,并改動(dòng)它。這也是JavaBean的標(biāo)準(zhǔn)實(shí)現(xiàn)方式之一。

          2. 如果instance變量是一個(gè)對(duì)象,如數(shù)組或ArrayList什么的,那上述方法仍然不安全,因?yàn)楫?dāng)外界對(duì)象通過get方法拿到這個(gè)instance對(duì)象

          的引用后,又將其指向另一個(gè)對(duì)象,那么這個(gè)private變量也就變了,豈不是很危險(xiǎn)。 這個(gè)時(shí)候就需要將get方法也加上synchronized同步,并

          且,只返回這個(gè)private對(duì)象的clone()――這樣,調(diào)用端得到的就是對(duì)象副本的引用了

          posted @ 2012-08-29 17:47 japper 閱讀(346) | 評(píng)論 (0)編輯 收藏

          2012年7月20日 #

          MyEclipse的一些配置及優(yōu)化

          MyEclipse的基礎(chǔ)配置:


          1. 先安裝MyEclipse,安裝MyEclipse7.5需要VPN代理,安裝過程大概持續(xù)10-15分鐘,使用VPN測(cè)試帳號(hào)即可

          2. 進(jìn)行MyEclipse的配置,
                從菜單欄中進(jìn)入“Windows --> Preferences”

          3. 先要進(jìn)行JDK的配置,
              在左側(cè)欄中選擇“Java --> Installed JREs”,
              按“Add”按鈕進(jìn)行添加

          4. 在彈出的“Add JRE”畫面中,選擇JRE的目錄,
              就是選擇你所在的JDK的目錄,我的為:C:\Program Files\Java\jre6
              在JRE名稱一欄中,填下想取的名稱,我這里叫“HiJackson's JRE”,
              然后“OK”確定

          5. 返回到設(shè)置框中,將剛剛配置的JRE選中

          6. 將Tomcat Server設(shè)為可用,并設(shè)置Tomcat的安裝目錄

          7. 在Tomcat的JDK中選擇剛剛配置的JDK

          8. 配置完成了,三個(gè)地方可以啟動(dòng)它的服務(wù),根據(jù)自己的喜好吧~~~




           

           

          優(yōu)化MyEclipse:

          1、去除不需要加載的模塊

          一個(gè)系統(tǒng)20%的功能往往能夠滿足80%的需求,MyEclipse也不例外,我們?cè)诖蠖鄶?shù)時(shí)候只需要20%的系統(tǒng)功能,所以可以將一些不使用的模塊禁止 加載啟動(dòng)。通過Windows - Preferences打開配置窗口,依次選擇左側(cè)的General - Startup and Shutdown,這個(gè)時(shí)候在右側(cè)就顯示出了Eclipse啟動(dòng)時(shí)加載的模塊,可以根據(jù)自己的實(shí)際情況去除一些模塊。
          windows–>perferences–>general–>startup and shutdown

          關(guān)掉沒用的啟動(dòng)項(xiàng):

          WTP :一個(gè)跟myeclipse差不多的東西,主要差別是 WTP 是免費(fèi)的,如果使用myeclipse,這個(gè)可以取消
          Mylyn:組隊(duì)任務(wù)管理工具,類似于 CVS ,以任務(wù)為單位管理項(xiàng)目進(jìn)度,沒用到的可以取消
          Derby:一種保存成 jar 形式的數(shù)據(jù)庫(kù),我沒用到,取消
          一大排以 MyEclipse EASIE 打頭的啟動(dòng)項(xiàng):myeclipse 支持的服務(wù)器,只選自己用的,其他取消,比如我只選了tomcat6.x

          2、取消MyEclipse在啟動(dòng)時(shí)自動(dòng)驗(yàn)證項(xiàng)目配置文件

          默認(rèn)情況下MyEclipse在啟動(dòng)的時(shí)候會(huì)自動(dòng)驗(yàn)證每個(gè)項(xiàng)目的配置文件,這是一個(gè)非常耗時(shí)的過程,
          可以在Preferences窗口依次選擇 MyEclipse Enterprise Workbench - Validation,然后在右側(cè)的Validator列表中只保留 Manual 項(xiàng)就可以了(Manual全部勾選,Bulid項(xiàng)只留下第一項(xiàng))。
          如果需要驗(yàn)證的時(shí)候只需要選中文件,然后右鍵選擇 MyEclipse - Run Validation就可以了。

          windows–>perferences–>myeclipse–>validation
          把 除了manual 下面的全部點(diǎn)掉,build下只留 classpath dependency Validator

          手工驗(yàn)證方法:

          在要驗(yàn)證的文件上,單擊鼠標(biāo)右鍵–>myeclipse–>run validation


          3、去掉拼寫檢查(如果你覺的有用可以不去)

          拼寫檢查會(huì)給我們帶來不少的麻煩,我們的方法命名都會(huì)是單詞的縮寫,他也會(huì)提示有錯(cuò),所以最好去掉,沒有多大的用處:
          windows–>perferences–>general–>validation->editors->Text Editors->spelling

          myeclipse 打開 jsp 的默認(rèn)編輯器不好,會(huì)同時(shí)打開預(yù)覽
          windows–>perferences–>general–>editors->file associations,

          把默認(rèn)改成 MyEclipse JSP Editor()
          原默認(rèn)的jsp編輯器是 MyEclipse Visual JSP Designer,顧名思義,此編譯器是jsp可視化編輯器,對(duì)于初學(xué)者有很多的幫助,
          但修改此項(xiàng)的默認(rèn)編輯器其實(shí)可以提高啟動(dòng)速度)

          4、關(guān)閉自動(dòng)更新

          如果是myeclipse7.5:

          (1)關(guān)掉maven自動(dòng)更新:

          window-preferences-MyEclipse Enterprise Workbench-Maven4MyEclipse-Maven,
          關(guān)閉所有Download和Update開頭的選項(xiàng),共四項(xiàng)(去掉前面的勾)

          (2)關(guān)閉更新調(diào)度:window –> preferences –> General –> Startup and Shutdown –> Automatic Updates Scheduler(去掉前面的勾)

          (3)window –> preferences –>Myeclipse Dashboard,關(guān)閉Show……on start

          5、加大JVM的非堆內(nèi)存

          打開 myeclipse.ini
          -startup
          ../Common\plugins\org.eclipse.equinox.launcher_1.0.101.R34x_v20081125.jar
          --launcher.library
          ../Common\plugins\org.eclipse.equinox.launcher.win32.win32.x86_1.0.101.R34x_v20080731
          -clean
          -configuration
          configuration
          -vm
          C:\Users\lenovo\AppData\Local\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\bin\client\jvm.dll
          -vmargs
          -Xmx384m
          -XX:MaxPermSize=384m
          -XX:ReservedCodeCacheSize=96m

          以上是我的myeclipse.ini,需要修改是-Xmx,-XX:MaxPermSize,-XX:ReservedCodeCacheSize,
          將這三項(xiàng)的值調(diào)大,但并不是越大越好,曾經(jīng)在相同的條件下做過測(cè)試(內(nèi)存2GB),-Xmx,-XX:MaxPermSize的值為384m時(shí)比512m時(shí)要快(視具體的計(jì)算機(jī)而定),
          -Xmx,-XX:MaxPermSize的值設(shè)為同樣大小且兩者之和不能超出你的計(jì)算機(jī)本身的內(nèi)存大小

          6、window-preferences-MyEclipse Enterprise Workbench-Maven4MyEclipse-Maven,將Maven JDK改為電腦上安裝的JDK,即不使用myeclipse提高的JDK
          登記add按鈕,選擇你的電腦上的JDK即可(注意:不是JRE,我的值為:Java6.014)

          7、window-preferences-MyEclipse Enterprise Workbench-Matisse4Myeclipse/Swing,將Design-time information(dt.jar) location 改用電腦安裝的JDK的dt.jar
          (即不使用myeclipse提供的dt.jar,我的值為:C:\Java6.014\lib\dt.jar)

          經(jīng)過以上的優(yōu)化,myeclipse的啟動(dòng)時(shí)間可以減少2/3,Tomcat的啟動(dòng)速度可以減少1/2(視具體情況而定),

          特別6,7兩項(xiàng)的優(yōu)化效果最明顯,

          如果只進(jìn)行前5項(xiàng),優(yōu)化的效果有限,短期內(nèi)確實(shí)可以提高啟動(dòng)速度,但是大概半個(gè)月后又會(huì)變的很慢(具體原因不明)
          另外,使用myeclipse一段時(shí)間后,就會(huì)產(chǎn)生很多項(xiàng)目,即使這些項(xiàng)目是處于關(guān)閉狀態(tài),myecliose在啟動(dòng)時(shí)也會(huì)加載這些項(xiàng)目,這個(gè)過程會(huì)花費(fèi)很多時(shí)間,所以,建議將不用的項(xiàng)目都delete掉,用的時(shí)候再import

          在用[MyEclipse] 寫代碼很容易卡死機(jī),尤其是在對(duì)JSP文件的﹤%%﹥之間寫代碼的時(shí)候,只要一彈出智能提示就立刻卡死,程序失去響應(yīng),我以為是MyEclipse版本的問題,結(jié)果換了6.0版-﹥6.5版-﹥7.0版全都一樣,難道是我機(jī)子的問題?可是還原系統(tǒng)后用還是一樣的結(jié)果。

          百度一下你就知道,但是百度了N下才找到了一些門路,搜索也講究技巧,換了N個(gè)[關(guān)鍵字] 組合才搜出來。說是MyEclipse在智能提示的時(shí)候自動(dòng)訪問網(wǎng)絡(luò)上sun公司的最新API文檔,只要關(guān)閉掉網(wǎng)絡(luò)連接就可以了。我試了試斷開網(wǎng)絡(luò)然后在用MyEclipse寫代碼,結(jié)果還真的搞定了。可是,我總不能因?yàn)閭€(gè)這就不上網(wǎng)了吧,繼續(xù)接著百度,找到了兩全其美的解決方法。

          在自己創(chuàng)建的工程名上右鍵,選擇Properties--﹥?cè)诖蜷_的窗口中點(diǎn)擊Java Build Path--﹥單擊Libraries選項(xiàng)卡,找到如圖中標(biāo)記2所示的地方--﹥選擇右邊的Remove更改成如標(biāo)記1所示的樣子--﹥點(diǎn)擊OK。


          posted @ 2012-07-20 10:25 japper 閱讀(1013) | 評(píng)論 (0)編輯 收藏

          2012年7月17日 #

          jquery筆記0717

          1、不常用的切換函數(shù)$("p").toggle();當(dāng)點(diǎn)擊切換按鈕時(shí),隱藏元素為P行和顯示P行;

          <html>
          <head>
          <script type="text/javascript" src="/jquery/jquery.js"></script>
          <script type="text/javascript">
          $(document).ready(function(){
            $("button").click(function(){
            $("p").toggle();
            });
          });
          </script>
          </head>
          <body>
          <button type="button">切換</button>
          <p>This is a paragraph with little content.</p>
          <p>This is another small paragraph.</p>
          </body>
          </html>

          2、append() 函數(shù)向所匹配的 HTML 元素內(nèi)部追加內(nèi)容$(selector).append(content);
          <html>
          <head>
          <script type="text/javascript" src="/jquery/jquery.js"></script>
          <script type="text/javascript">
          $(document).ready(
          function(){
            $(
          "button").click(function(){
            $(
          "p").append(" <b>W3School</b>.");
            }
          );
          }
          );
          </script>
          </head>

          <body>
          <h2>This is a heading</h2>
          <p>This is a paragraph.</p>
          <p>This is another paragraph.</p>
          <button type="button">請(qǐng)點(diǎn)擊這里</button>
          </body>

          </html>
          類似的還有:
          $(selector).html(content) 改變被選元素的(內(nèi)部)HTML
          $(selector).append(content) 向被選元素的(內(nèi)部)HTML 追加內(nèi)容
          $(selector).prepend(content) 向被選元素的(內(nèi)部)HTML “預(yù)置”(Prepend)內(nèi)容
          $(selector).after(content) 在被選元素之后添加 HTML
          $(selector).before(content) 在被選元素之前添加 HTML

          3、css操作:函數(shù) css({properties}) 同時(shí)為所有匹配元素的一系列 CSS 屬性設(shè)置值:
          $(selector).css({properties})
          $("p").css({"background-color":"red","font-size":"200%"});

          jQuery 擁有兩種用于尺寸操作的重要函數(shù):

          • $(selector).height(value)
          • $(selector).width(value)
          總結(jié)如:
          $(selector).css(name,value) 為匹配元素設(shè)置樣式屬性的值
          $(selector).css({properties}) 為匹配元素設(shè)置多個(gè)樣式屬性
          $(selector).css(name) 獲得第一個(gè)匹配元素的樣式屬性值
          $(selector).height(value) 設(shè)置匹配元素的高度
          $(selector).width(value) 設(shè)置匹配元素的寬度

          4、AJAX:

          jQuery AJAX 請(qǐng)求
          $(selector).load(url,data,callback) 把遠(yuǎn)程數(shù)據(jù)加載到被選的元素中
          $.ajax(options) 把遠(yuǎn)程數(shù)據(jù)加載到 XMLHttpRequest 對(duì)象中
          $.get(url,data,callback,type) 使用 HTTP GET 來加載遠(yuǎn)程數(shù)據(jù)
          $.post(url,data,callback,type) 使用 HTTP POST 來加載遠(yuǎn)程數(shù)據(jù)
          $.getJSON(url,data,callback) 使用 HTTP GET 來加載遠(yuǎn)程 JSON 數(shù)據(jù)
          $.getScript(url,callback) 加載并執(zhí)行遠(yuǎn)程的 JavaScript 文件

          (url) 被加載的數(shù)據(jù)的 URL(地址)

          (data) 發(fā)送到服務(wù)器的數(shù)據(jù)的鍵/值對(duì)象

          (callback) 當(dāng)數(shù)據(jù)被加載時(shí),所執(zhí)行的函數(shù)

          (type) 被返回的數(shù)據(jù)的類型 (html,xml,json,jasonp,script,text)

          (options) 完整 AJAX 請(qǐng)求的所有鍵/值對(duì)選項(xiàng)

          略。。。


















          posted @ 2012-07-17 11:21 japper 閱讀(384) | 評(píng)論 (0)編輯 收藏

          2012年7月16日 #

          使用jxl導(dǎo)出大數(shù)據(jù)量EXCEL時(shí)內(nèi)存溢出的解決辦法

          1、通過jx1最新版本的采用臨時(shí)文件寫入EXCEL功能,設(shè)定臨時(shí)文件的位置,可以有效的避免內(nèi)存溢出:
                      wbSetting.setUseTemporaryFileDuringWrite(true);   
                      wbSetting.setTemporaryFileDuringWriteDirectory(new File(excelPath));//臨時(shí)文件夾的位置


          2、EXCEL獲取的list集合先讀取數(shù)據(jù)總行數(shù),再通過ROWNUM進(jìn)行控制,設(shè)定每次讀取多少行數(shù)據(jù),比如一個(gè)List設(shè)定為50000;
                      WorkbookSettings wbSetting = new WorkbookSettings();   
                      wbSetting.setUseTemporaryFileDuringWrite(true);   
                      wbSetting.setTemporaryFileDuringWriteDirectory(new File(excelPath));//臨時(shí)文件夾的位置
                      workbook = Workbook.createWorkbook(new File(fullPath),wbSetting);
                      int returnCount=0;
                      if(null!=pager)
                      {
                          returnCount = BrasDatabase.getReturnCount(pager.getStartTime(),
                                  pager.getEndTime(), pager);
                      }

                      if (returnCount > 0) {    
                          pager.setPageSize(50000);
                          pager.setTotalRows(returnCount);// 獲取總行數(shù)
                          pager.setNewTotalPages(pager.getTotalRows()); // 總頁數(shù)
                          for (int i = 1; i 
          <= pager.getTotalPages(); i++) {
                              pager.setCurrentPage(i); // 當(dāng)前頁面d
                              List<BrasAuth
          > list = BrasDatabase
                                      .getBrasAuthResultByIpToExcelList(pager
                                              .getStartTime(), pager.getEndTime(), pager);
                              this.createExcel(list,excelFilePath);
                              list.clear();
                          }
                      }



          3、在寫入EXCEL的時(shí)候,將讀取的LIST分割,每50000條數(shù)據(jù)生成一個(gè)EXCEL的sheet(一個(gè)sheet最多能存儲(chǔ)60000多行數(shù)據(jù)),再寫入,寫入的時(shí)候,如果設(shè)置了采用臨時(shí)文件寫入的話,jx1會(huì)自動(dòng)采用生成臨時(shí)文件的方式寫入EXCEL:
                  for(int i=1;i<=list.size();i++)
                  {
                      if(i%50000
          ==0)
                      
          {
                          sheetName
          =format.format(new Date());
                          toExcel(list.subList(reNum, i),sheetName);
                          reNum
          =i;
                      
          }
                  }

          posted @ 2012-07-16 11:48 japper 閱讀(8908) | 評(píng)論 (1)編輯 收藏

          僅列出標(biāo)題  下一頁
          主站蜘蛛池模板: 莲花县| 商河县| 马龙县| 巢湖市| 台湾省| 克什克腾旗| 大足县| 布拖县| 凤冈县| 榆社县| 宜兰县| 阿尔山市| 华蓥市| 乐业县| 金阳县| 灌阳县| 衡阳县| 桐城市| 本溪市| 吉木萨尔县| 云浮市| 乌拉特后旗| 柯坪县| 玉门市| 沅江市| 东方市| 勃利县| 新平| 蓬安县| 定兴县| 射洪县| 丰台区| 招远市| 万州区| 银川市| 阳原县| 葫芦岛市| 宜阳县| 丰顺县| 临清市| 揭西县|