﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-都市淘沙者-文章分类-Java Basic/Lucene/开源资料</title><link>http://www.blogjava.net/jelver/category/7676.html</link><description>每天进步一点点</description><language>zh-cn</language><lastBuildDate>Thu, 10 Nov 2011 08:36:14 GMT</lastBuildDate><pubDate>Thu, 10 Nov 2011 08:36:14 GMT</pubDate><ttl>60</ttl><item><title>BeanComparator实现ArrayList复合排序[转]</title><link>http://www.blogjava.net/jelver/articles/363386.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 10 Nov 2011 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/363386.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/363386.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/363386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/363386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/363386.html</trackback:ping><description><![CDATA[<div><a href="http://blog.csdn.net/ftlovexg/article/details/1583757">http://blog.csdn.net/ftlovexg/article/details/1583757</a></div><div><p>研究了几天,那时候就是认为要继承Comparable接口,重写CompareTo方法,结果走向了歧路.后来就搜啊搜,发现了点东西.自己又总结了下.<strong>需要的JAR包:commons.collections.jar</strong></p> <div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid"> <div><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;test;<br /><br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.Collections;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.Comparator;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.ArrayList;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.commons.beanutils.BeanComparator;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.commons.collections.ComparatorUtils;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.commons.collections.comparators.ComparableComparator;<br /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;org.apache.commons.collections.comparators.ComparatorChain;<br /><br /></span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;CompareTipA&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span>&nbsp;<span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;&nbsp;id;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;age;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">static</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String&nbsp;[]args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Object</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;list&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Object</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">3</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">五</span><span style="color: #000000">"</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">1</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">六</span><span style="color: #000000">"</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">5</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">二</span><span style="color: #000000">"</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">4</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">四</span><span style="color: #000000">"</span><span style="color: #000000">));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #000000">4</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">2</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">一</span><span style="color: #000000">"</span><span style="color: #000000">));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comparator&nbsp;mycmp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;ComparableComparator.getInstance();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mycmp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;ComparatorUtils.nullLowComparator(mycmp);&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">允许null&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mycmp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;ComparatorUtils.reversedComparator(mycmp);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">逆序&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Object</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;sortFields&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Object</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sortFields.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;BeanComparator(</span><span style="color: #000000">"</span><span style="color: #000000">id</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;mycmp));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">id逆序&nbsp;&nbsp;(主)</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sortFields.add(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;BeanComparator(</span><span style="color: #000000">"</span><span style="color: #000000">name</span><span style="color: #000000">"</span><span style="color: #000000">));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">name正序&nbsp;(副)</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ComparatorChain&nbsp;multiSort&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ComparatorChain(sortFields);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collections.sort(list,multiSort);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">list.size();i</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(list.get(i));&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">输出</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;CompareTipA(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;id,&nbsp;String&nbsp;name,String&nbsp;age)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.id&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;id;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.name&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.age&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;age;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;getId()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span>&nbsp;<span style="color: #0000ff">this</span><span style="color: #000000">.id;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setId(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;id)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.id&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;id;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;getName()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span>&nbsp;<span style="color: #0000ff">this</span><span style="color: #000000">.name;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setName(String&nbsp;name)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.name&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;name;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;compareTo(Object&nbsp;o)&nbsp;{<br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;this.comparator.compare(this,&nbsp;o);<br /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008000"><br /></span><span style="color: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;toString()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span>&nbsp;<span style="color: #000000">"</span><span style="color: #000000">[id=</span><span style="color: #000000">"</span>&nbsp;<span style="color: #000000">+</span>&nbsp;<span style="color: #0000ff">this</span><span style="color: #000000">.id&nbsp;</span><span style="color: #000000">+</span>&nbsp;<span style="color: #000000">"</span><span style="color: #000000">,name=</span><span style="color: #000000">"</span>&nbsp;<span style="color: #000000">+</span>&nbsp;<span style="color: #0000ff">this</span><span style="color: #000000">.name&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">"</span><span style="color: #000000">,age=</span><span style="color: #000000">"</span>&nbsp;<span style="color: #000000">+</span>&nbsp;<span style="color: #0000ff">this</span><span style="color: #000000">.age&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">"</span><span style="color: #000000">]</span><span style="color: #000000">"</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;getAge()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;age;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setAge(String&nbsp;age)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.age&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;age;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}&nbsp;<br /></span></div> </div> &nbsp; </div><img src ="http://www.blogjava.net/jelver/aggbug/363386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2011-11-10 10:45 <a href="http://www.blogjava.net/jelver/articles/363386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开源中最好的Web开发的资源</title><link>http://www.blogjava.net/jelver/articles/352472.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 16 Jun 2011 23:58:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/352472.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/352472.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/352472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/352472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/352472.html</trackback:ping><description><![CDATA[<div><p>文章来源：<a title="Best &#8220;must know&#8221; open sources to build the new Web" href="http://www.b2bweb.fr/molokoloco/best-must-know-ressources-for-building-the-new-web-%E2%98%85/" target="_blank">Best &#8220;must know&#8221; open sources to build the new Web</a>。个人感觉这个收集贴收集成相当的全。</p> <h4>学习HTML 5编程和设计</h4> <p><img title="wallOfWonder" src="http://www.b2bweb.fr/wp-content/uploads/wallOfWonder.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://www.html5rocks.com/" target="_blank"><strong>HTML5 Rocks</strong></a> : Major Feature Groups &nbsp;的学习&nbsp;HTML5 的资源&nbsp;(HTML5 演示, 教程 ).&nbsp;<a href="http://code.google.com/p/html5rocks/" target="_blank">源码</a></li><li>很不错的&nbsp;<a href="https://mozillademos.org/demos/dashboard/demo.html" target="_blank"><strong>HTML5 Dashboard</strong></a> &#8211; Mozilla，效果很炫。</li><li><a href="http://developers.whatwg.org/" target="_blank"><strong>WhatWG Developers</strong></a>, 一个清楚的 HTML5 技术规格说明书。</li><li>&#9733;&nbsp;<a href="http://stackoverflow.com/" target="_blank"><strong>StackOverflow</strong></a> : 大名鼎鼎的技术问答式论坛。</li><li>&#9733;&nbsp;<a href="http://addyosmani.com/blog/" target="_blank"><strong>Addyosmani</strong></a>, jQuery 和 JavaScript 文章教程</li><li><a href="http://www.sohtanaka.com/web-design-tutorials/" target="_blank"><strong>Sohtanaka</strong></a>, jQuery 和 JavaScript 文章和教程</li><li>&#9733;&nbsp;<a href="http://net.tutsplus.com/category/tutorials/" target="_blank"><strong>Nettuts+</strong></a> 是一个面对Web开发人员和设计人员的网站，提供各种技术教程和文章，覆盖 HTML, CSS, Javascript, CMS&#8217;s, PHP 和 Ruby on Rails.</li><li><a href="http://tympanus.net/codrops/" target="_blank"><strong>Codrops</strong></a>, 教程和 web 资源</li><li><a href="http://www.webappers.com/" target="_blank"><strong>WebAppers</strong></a>, 最好的开源资源</li><li><a href="http://tutorialzine.com/" target="_blank"><strong>Tutorialzine</strong></a> &#8211; PHP MySQL jQuery CSS 教程, 资源和赠品</li><li><strong><a href="https://developer.mozilla.org/en/JavaScript/Guide" target="_blank">Mozilla JavaScript guide</a></strong></li><li> <a href="http://code.google.com/p/molokoloco-coding-project/" target="_blank"><strong>codes snippets</strong></a>, 作者自己收集的一些代码片段</li></ul> <h4>服务器端的软件</h4> <p><img title="nodeJs" src="http://www.b2bweb.fr/wp-content/uploads/nodeJs.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://nodejs.org/" target="_blank"><strong>Node.js</strong></a> 是服务器端的 JavaScript 环境，其使用了异步事件驱动模式。其让Node.js在很多互联网应用体系结构下获得非常不错的性能。&nbsp;<a href="https://github.com/joyent/node/" target="_blank">源码</a> 和&nbsp;<a href="http://jsapp.us/" target="_blank">实时演示</a>。</li><li><a href="http://www.phantomjs.org/" target="_blank"><strong>PhantomJS</strong></a> 也是一个服务器端的 JavaScript API的WebKit。其支持各种Web标准：&nbsp;DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG</li><li><strong><a href="http://www.lighttpd.net/" target="_blank">Lighttpd</a></strong> 一个轻量级的开源Web服务器。新闻，文档，benchmarks, bugs, 和 download. Lighttpd 支撑了几个非常著名的 Web 2.0 网站，如：YouTube, wikipedia 和 meebo.</li><li><strong><a href="http://nginx.net/" target="_blank">NGinx</a></strong>, 性能巨高无比的轻量级的Web服务器。比Apache高多了。花了6年的时间，终于走到了1.0版。</li><li><strong><a href="http://httpd.apache.org/" target="_blank">Apache HTTP Server</a></strong> 是一个很流行的并支持多个流行的操作系统的Web服务器。</li><li>&#9733;&nbsp;<strong><a href="http://www.php.net/" target="_blank">PHP</a></strong> 可能是最流行的服务器端的Web脚本动态处理语言。</li><li>当然，还有&nbsp;<strong><a href="http://www.ruby-lang.org/fr/" target="_blank">Ruby</a></strong>,&nbsp;<strong><a href="http://www.python.org/" target="_blank">Python</a></strong>,&nbsp;<strong><a href="http://www.erlang.org/" target="_blank">Erlang</a></strong>,&nbsp;<strong><a href="http://www.perl.org/" target="_blank">Perl</a></strong>,&nbsp;<strong><a href="http://www.java.com/fr/" target="_blank">Java</a></strong>,&nbsp;<strong><a href="http://www.microsoft.com/net/" target="_blank">.NET</a></strong>,&nbsp;<strong><a href="http://www.android.com/" target="_blank">Android</a></strong>,&nbsp;<strong><a href="http://cpp.developpez.com/" target="_blank">C++</a></strong>,&nbsp;<strong><a href="http://golang.org/" target="_blank">Go</a></strong>,<strong><a href="http://fantom.org/" target="_blank"> Fantom</a></strong>,<strong><a href="http://jashkenas.github.com/coffee-script/" target="_blank">CoffeeScript</a></strong>,&nbsp;<strong><a href="http://www.digitalmars.com/" target="_blank">D</a></strong>, &#8230;</li></ul> <h4>PHP 框架和工具</h4> <p><img title="drupal" src="http://www.b2bweb.fr/wp-content/uploads/drupal.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://wordpress.org/download/" target="_blank"><strong>WordPress</strong></a> 是一个基于博客系统的开源软件。参看《<a title="WordPress是怎么赢的？" href="http://coolshell.cn/articles/3716.html" target="_blank">WordPress是怎么赢的？</a>》</li><li><strong><a href="http://drupal.org/" target="_blank">Drupal</a></strong> 是一个内容管理系统 (CMS).</li><li><a href="http://www.centurion-project.org/" target="_blank"><strong>Centurion</strong></a> 是一个新出现的开源 CMS ，一个灵然的 PHP5 Content Management Framework. 使用 Zend Framework, 其组件坚持通用，简单，清楚和可重用的设计原则。</li><li><strong><a href="http://www.phpbb.com/" target="_blank">phpBB</a></strong> 一个开源的论坛（国内的Discuz！更多）</li><li><strong>&#9733;&nbsp;<a href="http://simplepie.org/" target="_blank">SimplePie</a></strong> : 超快的，易用的, &nbsp;RSS &nbsp;和 Atom feed PHP解析。</li><li><strong>&#9733;&nbsp;<a href="http://phpthumb.gxdlabs.com/" target="_blank">PHPthumb</a></strong>, PHP 图片处理库</li><li><strong>&#9733;&nbsp;<a href="http://phpmailer.worxware.com/" target="_blank">PHPMailer</a></strong> 强大的全功能的PHP邮件库</li><li><strong><a href="http://code.google.com/p/pubsubhubbub/" target="_blank">PubSubHubbub</a></strong>协议，一个简单，开放， server-to-server 的 pubsub (publish/subscribe) 协议&#8212;&#8212;Atom and RSS的扩展。</li><li>更多的请参看 &#8211; <a title="20 你应该知道的PHP库" href="http://coolshell.cn/articles/200.html" target="_blank">20个你应该知道PHP库</a> 和&nbsp;<a title="9个强大免费的PHP库" href="http://coolshell.cn/articles/455.html" target="_blank">9个强大免费的PHP库</a></li></ul> <h4>数据库</h4> <p><img title="sqldesigner" src="http://www.b2bweb.fr/wp-content/uploads/sqldesigner.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://couchdb.apache.org/" target="_blank"><strong>Apache CouchDB</strong></a> 是一个面向文档的数据库管理系统。它提供以JSON 作为数据格式的REST 接口来对其进行操作，并可以通过视图来操纵文档的组织和呈现。.<a href="https://github.com/apache/couchdb" target="_blank">源码</a>.</li><li><a href="http://code.google.com/p/monoql/" target="_blank"><strong>MonoQL</strong></a> 是一个采用PHP+ExtJS开发的MySQL数据库管理工具。界面极像一个桌面应用程序，支持大部分常用的功能包括：表格设计，数据浏览/编辑，数据导入/导出和高级查询等。</li><li><strong> </strong><a href="http://mariadb.org/"><strong>MariaDB</strong></a> 是<a title="MySQL" href="http://www.mysql.com/" target="_blank">MySQL</a>的一个分支，由MySQL 创始人Monty Widenius 所开发。GPL，用来对抗Oracle所有的MySQL的license的不测。自Oracle收购SUN以来，整个社区对于MySQL前途的担忧就没有停止过。</li><li>&#9733;&nbsp;<a href="http://www.sqlite.org/" target="_blank"><strong>SQLite</strong></a>   不像常见的客户端/服务器结构范例，SQLite引擎不是个程序与之通信的独立进程，而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程   语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库（定义、表、索引和数据本身）都在宿主主机上存储在一个单一的文   件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。库实现了多数的SQL-92标准，包括事务，就是代表原子性、一致性、隔离性   和持久性的（ACID），触发器和多数的复杂查询。不进行类型检查。你可以把字符串插入到整数列中。某些用户发现这是使数据库更加有用的创新，特别是与无  类型的脚本语言一起使用的时候。其他用户认为这是主要的缺点。</li><li><strong><a href="http://ondras.zarovi.cz/sql/demo/" target="_blank">SQL 在线设计编辑器</a></strong>，这一节的那个图片就是这个在线编辑器的样子了。一个画数据库图表的在线工具。很强大。</li></ul> <h4>API 和 在线数据</h4> <p><img title="yql" src="http://www.b2bweb.fr/wp-content/uploads/yql.png" alt="" height="238" width="600" /></p> <ul><li><a href="http://www.programmableweb.com/apis/directory" target="_blank"><strong>ProgrammableWeb</strong></a>, 最流行的Web Services 和 API 目录大全。</li><li><strong><a href="http://code.google.com/intl/fr/apis/gdata/docs/directory.html" target="_blank">Google Data Protocol</a></strong> 一组Google服务的数据服务API。</li><li><a href="http://developer.yahoo.com/everything.html" target="_blank"><strong>Yahoo! Developer Network</strong></a> &#8211; APIs 和 Tools</li><li><a href="http://pipes.yahoo.com/" target="_blank"><strong>Yahoo! Pipes</strong></a> 可视化在线编程工具，它是一个用于过滤、转换和聚合网页内容的服务。</li><li>&#9733;&nbsp;The&nbsp;<a href="http://developer.yahoo.com/yql/console/" target="_blank"><strong>Yahoo! Query Language</strong></a> 一个很像 SQL的网页查询工具。</li></ul> <h4>在线代码和媒体编辑器</h4> <p><img title="jsfiddle" src="http://www.b2bweb.fr/wp-content/uploads/jsfiddle.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://www.coderun.com/" target="_blank"><strong>CodeRun Studio</strong></a>一个基于JavaScript语言开发的跨平台的集成开发环境，它立足于云计算的设计思路，方便开发者在浏览器端便可以轻松开发、调试和部署网络应用程序。（参看《<a rel="bookmark" href="http://coolshell.cn/articles/1883.html" target="_blank">Coderun.com 在线开发IDE</a>》）</li><li><a href="https://github.com/ajaxorg/cloud9" target="_blank"><strong>Cloud9 IDE</strong></a> &#8211; 一个基于Node.JS构建的JavaScript程序开发Web IDE。它拥有一个非常快的文本编辑器支持为JS, HTML, CSS和这几种的混合代码进行着色显示。</li><li>&#9733;&nbsp;<a href="http://jsfiddle.net/" target="_blank"><strong>jsFiddle</strong></a>  &#8211; Javascript的在线运行展示框架，这个工具可以有效的帮助web前端开发人员来有效分享和演示前端效果，其简单而强大   (JavaScript, MooTools, jQuery, Prototype, YUI, Glow and Dojo, HTML, CSS)</li><li><strong><a href="http://www.akshell.com/" target="_blank">Akshell</a>，</strong>一种云服务，它使用服务端的JavaScript和在线的IDE帮助开发者进行快速应用程序开发。 它还提供云托管，所以部署是即时的。</li><li><a href="http://braincast.nl/samples/jsoneditor/" target="_blank"><strong>JSONeditor</strong></a>, 一个好用的JSON 编辑器</li><li>&#9733;&nbsp;<a href="http://tinymce.moxiecode.com/wiki.php/TinyMCE" target="_blank"><strong>TinyMCE</strong></a> 一个轻量级的基于浏览器的所见即所得编辑器，支持目前流行的各种浏览器，由JavaScript写成。</li><li><a href="http://www.sencha.com/products/designer/" target="_blank"><strong>Ext Designer</strong></a> 是一个桌面应用工具，帮助你快速开发基于ExtJS 的用户界面。</li><li>&#9733; &nbsp;<strong><a href="http://www.lucidchart.com/" target="_blank">LucidChart</a></strong>，一款基于最新的html5技术的在线图表绘制软件，功能强大，速度快捷，运行此软件需要支持html5的浏览器。</li><li><a href="http://balsamiq.com/products/mockups" target="_blank"><strong>Balsamiq Mockups</strong></a>, 产品设计师绘制线框图或产品原型界面的利器。</li><li><a href="http://colorschemedesigner.com/" target="_blank"><strong>Color Scheme Designer</strong></a> 3 -&nbsp;一个免费的线上调色工具</li><li>&#9733;&nbsp;<a href="http://pixlr.com/editor/" target="_blank"><strong>Pixlr</strong></a>, 是一个来自瑞典基于Flash的免费在线图片处理网站。除了操作介面和功能接近Photoshop，还是多语言版本，支持简体中文。（以前<a title="在线作图编辑服务" href="http://coolshell.cn/articles/3244.html" target="_blank">酷壳介绍过</a>）</li><li><a href="http://www.aviary.com/" target="_blank"><strong>Aviary</strong></a>, 是一个基于HTML5 的在线图片处理工具，可以很容易的对图片进行后期处理。&nbsp;<a href="http://developers.aviary.com/" target="_blank">Aviary API</a></li><li><strong><a href="http://www.degraeve.com/favicon/" target="_blank">Favicon Generator</a>, </strong>线上favicon(16&#215;16)制作工具。</li></ul> <h4>代码资源和版本控制</h4> <p><img title="github" src="http://www.b2bweb.fr/wp-content/uploads/github.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="https://github.com/" target="_blank"><strong>GitHub</strong></a> 是一个用于使用Git版本控制系统的项目的基于互联网的存取服务。</li><li><a href="http://code.google.com/p/msysgit/" target="_blank"><strong>Git</strong></a> 是一个由Linus为了更好地管理linux内核开发而创立的分布式版本控制／软件配置管理软件。其巨快无比，高效，采用了分布式版本库的方式，不必服务器端软件支持，使源代码的发布和交流极其方便。</li><li><a href="http://code.google.com/" target="_blank"><strong>Google Code</strong></a> 谷歌公司官方的开发者网站，包含各种开发技术的API、开发工具、以及开发技术参考资料。</li><li><strong><a href="http://code.google.com/intl/zh-CN/apis/libraries/" target="_blank">Google Libraries API</a></strong> Google 将优秀的 JavaScript 框架部署在其 CDN 上，在我们的网站上使用 Google Libraries API&nbsp;可以加速 JavaScript 框架的加载速度。</li><li><a href="http://snipplr.com/" target="_blank"><strong>Snipplr</strong></a> 一个开放的源代码技巧分享社区，号称Code 2.0。和一般的源码分享网站不同，它针对的并不是大型网站源码，而是一些编程的代码技巧。</li></ul> <h4>JavaScript 桌面应用框架</h4> <p><img title="jqueryUI" src="http://www.b2bweb.fr/wp-content/uploads/jqueryUI.jpg" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://jquery.com/" target="_blank"><strong>jQuery</strong></a> 是一个快速、简单的JavaScript library， 它简化了HTML 文件的traversing，事件处理、动画、Ajax 互动，从而方便了网页制作的快速发展。&nbsp;&nbsp;<a href="https://github.com/jquery/jquery" target="_blank">源码</a>,&nbsp;<a href="http://api.jquery.com/" target="_blank">API</a>,&nbsp;<a href="http://api.jquery.com/browser/" target="_blank">API浏览</a>,&nbsp;<a href="http://interface.eyecon.ro/docs/animate" target="_blank">很不错的文档</a>.</li><li>&#9733; 官方的&nbsp;<a href="http://jqueryui.com/" target="_blank"><strong>jQuery User Interface (UI) library</strong></a> (演示和文档).&nbsp;<a href="https://github.com/jquery/jquery-ui%20" target="_blank">源码</a>,<a href="http://jqueryui.com/themeroller/" target="_blank">Themes Roller</a>,&nbsp;<a href="http://jqueryui.com/download" target="_blank">Download</a>.</li><li><a href="http://developer.yahoo.com/yui/2/" target="_blank"><strong>YUI 2</strong></a> &#8212; Yahoo! User Interface Library</li><li><a href="http://mootools.net/" target="_blank"><strong>Mootools</strong></a>, 一个超级轻量级的 web2.0 JavaScript framework</li><li><a href="http://www.prototypejs.org/" target="_blank"><strong>Prototype</strong></a> 提供面向对象的Javascript和AJAX</li><li><a href="http://dojotoolkit.org/" target="_blank"><strong>Dojo</strong></a>  The Dojo   Toolkit，一个强大的无法被打败的面向对象JavaScript框架。主要由三大模块组成：Core、Dijit、DojoX。Core提供  Ajax,events,packaging,CSS-based   querying,animations,JSON等相关操作API。Dijit是一个可更换皮肤，基于模板的WEB   UI控件库。DojoX包括一些创新/新颖的代码和控件：DateGrid，charts，离线应用，跨浏览器矢量绘图等。</li><li>&#9733;&nbsp;<a href="http://dev.sencha.com/deploy/ext-4.0.0/docs/" target="_blank"><strong>Ext JS 4</strong></a>, 业内最强大的 JavaScript framework。</li><li><a href="http://phpjs.org/functions/index" target="_blank"><strong>PHP.js</strong></a>, 一个开源的JavaScript 库，它尝试在JavaScript 中实现PHP 函数。在你的项目中导入<em>PHP.JS</em> 库，可以在静态页面使用你喜欢的PHP 函数。</li></ul> <h4>JavaScript 移动和触摸框架</h4> <p><img title="senchatouch" src="http://www.b2bweb.fr/wp-content/uploads/senchatouch.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://jquerymobile.com/" target="_blank"><strong>jQuery Mobile</strong></a>  : 是&nbsp;jQuery 在手机上和平板设备上的版本。jQuery Mobile   不仅会给主流移动平台带来jQuery核心库，而且会发布一个完整统一的jQuery移动UI框架。支持全球主流的移动平台。jQuery   Mobile开发团队说：能开发这个项目，我们非常兴奋。移动Web太需要一个跨浏览器的框架，让开发人员开发出真正的移动Web网站。我们将尽全力去满  足这样的需求。&nbsp;<a href="https://github.com/jquery/jquery-mobile" target="_blank">Sources</a>.</li><li><a href="http://zeptojs.com/" target="_blank"><strong>Zepto.js</strong></a> Zepto.js 是支持移动WebKit浏览器的JavaScript框架，具有与jQuery兼容的语法。2-5k的库，通过不错的API处理绝大多数的基本工作。&nbsp;<a href="https://github.com/madrobby/zepto" target="_blank">Sources</a>.</li><li><a href="http://microjs.com/" target="_blank"><strong>MicroJS</strong></a> : Microjs网站应用列出了很多轻量的Javascript类库和框架，它们都很小，大部分小于5kb。这样你不需要因为只需要一个功能就要加载一个JS的框架。</li><li>&#9733;&nbsp;<a href="http://phonegap.com/" target="_blank"><strong>PhoneGap</strong></a> :是一款开源的手机应用开发平台，它仅仅只用HTML和JavaScript语言就可以制作出能在多个移动设备上运行的应用。&nbsp;<a href="https://github.com/phonegap/phonegap" target="_blank">Sources</a>.</li><li>&#9733;&nbsp;<a href="http://www.sencha.com/products/touch/" target="_blank"><strong>Sencha Touch</strong></a>  Sencha Touch 是一个支持多种智能手机平台（iPhone, Android, 和BlackBerry）的 HTML5   框架。Sencha Touch可以让你的Web App看起来像Native   App。美丽的用户界面组件和丰富的数据管理，全部基于最新的HTML5和CSS3的 WEB标准，全面兼容Android和Apple iOS设备。</li><li><a href="http://jqtouch.com/" target="_blank"><strong>JQtouch</strong></a>, 是一个jQuery 的插件，主要用于手机上的Webkit 浏览器上实现一些包括动画、列表导航、默认应用样式等各种常见UI效果的JavaScript 库。&nbsp;<a href="http://github.com/senchalabs/jQTouch" target="_blank">Sources</a>.</li><li><a href="http://www.dhtmlx.com/touch/" target="_blank"><strong>DHTMLX Touch</strong></a>  针对移动和触摸设备的JavaScript 框架。DHTMLX Touch基于HTML5，创建移动web应用。它不只是一组UI   小工具，而是一个完整的框架，可以针对移动和触摸设备创建跨平台的web应用。它兼容主流的web浏览器，用DHTMLX   Touch创建的应用，可以在iPad、iPhone、Android智能手机等上面运行流畅。</li></ul> <h4>jQuery 插件</h4> <p><img title="flexiGrid" src="http://www.b2bweb.fr/wp-content/uploads/flexiGrid.jpg" alt="" height="238" width="600" /></p> <ul><li><a href="http://imakewebthings.github.com/jquery-waypoints/" target="_blank"><strong>Waypoints</strong></a> 是一个jQuery 用来实现捕获各种滚动事件的插件，例如实现无翻页的内容浏览，或者固定某个元素不让滚动等等。支持主流浏览器版本。</li><li><strong><a href="http://plugins.jquery.com/project/lazy" target="_blank">Lazy loader</a> </strong>插件可以实现图片的延迟加载，当网页比较长的时候，会先只加载用户视窗内的图片，视窗外的图片会等到你拖动滚动条至后面才加载，这样有效的避免了因图片过多而加载慢的弊端。</li><li><a href="https://github.com/gskinner/TweenJS" target="_blank"><strong>TweenJS</strong></a> : 一个简单和强大的 tweening / animation 的Javascript库。</li><li><a href="http://janne.aukia.com/easie/" target="_blank"> <strong>Easings</strong></a> 类Css3的jQuery 动画插件</li><li><a href="http://www.spritely.net/" target="_blank"><strong>Spritely</strong></a> 这个插件可以创建出如flash一样的动画效果，比如：在页面上有一只飞动的小鸟，一个动态滚动的背景等。</li><li><strong><a href="https://github.com/blueimp/jQuery-File-Upload/" target="_blank">File Upload</a>, </strong>jQuery 文件上传插件4.4.1</li><li><a href="http://www.agilecarousel.com/" target="_blank"><strong>Slideshow/Carousel</strong></a> 插件.&nbsp;<a href="https://github.com/edtalmadge/Agile-Carousel" target="_blank">Sources</a>.</li><li><a href="http://www.buildinternet.com/project/supersized/" target="_blank"><strong>Supersized</strong></a> &#8211; 全屏式的背景/幻灯片插件</li><li><a href="http://desandro.com/resources/jquery-masonry" target="_blank"><strong>Masonry</strong></a> i一款非常酷的自动排版插件，这款jQuery工具可以根据网格来自动排列水平和垂直元素，超越原来的css.&nbsp;<a href="https://github.com/desandro/masonry" target="_blank">Sources</a>.</li><li>jQuery 简单&nbsp;<a href="http://layout.jquery-dev.net/demos.cfm" target="_blank"><strong>Layout</strong></a> 演示，管理各种边栏式，可改变大小式的布局。</li><li><a href="http://www.flexigrid.info/" target="_blank"><strong>Flexigrid</strong></a> &#8211; jQuery&nbsp;<a href="http://www.flexigrid.info/" target="_blank"><strong> </strong></a>数据表插件</li><li><a href="http://isotope.metafizzy.co/" target="_blank"><strong>Isotope</strong></a>绝对是一个令人难以置信的<em>jQuery</em>插件，你可以用它来创建动态和智能布局。你可以隐藏和显示与过滤项目，重新排序和整理甚至更多。</li><li><a href="http://www.evanbyrne.com/article/super-gestures-jquery-plugin" target="_blank"><strong>Super Gestures</strong></a> jQuery 插件可以实现鼠标手势的功能。</li><li><a href="https://github.com/brandonaaron/jquery-mousewheel" target="_blank"><strong>MouseWheel</strong></a> 是由Brandon Aaron开发的<em>jQuery</em>插件，用于添加跨浏览器的鼠标滚轮支持。</li><li><a href="http://code.drewwilson.com/entry/autosuggest-jquery-plugin" target="_blank"><strong>AutoSuggest</strong></a> jQuery 插件可以让你添加一些自动完成的功能。</li><li><a href="http://craigsworks.com/projects/qtip/" target="_blank"><strong>qTip</strong></a> 一个漂亮的<em>jQuery</em> 的工具提示插件，这个插件功能相当强大。</li><li>jQuery&nbsp;<a href="http://www.highcharts.com/demo/" target="_blank"><strong>Charts and graphic</strong></a> 用来制作图表。</li><li>jQuery Tools&#8211; The&nbsp;<a href="http://flowplayer.org/tools/demos/" target="_blank"><strong>missing UI library</strong></a></li></ul> <h4>其它 jQuery 资源</h4> <ul><li><a href="http://www.smashingmagazine.com/2011/04/07/useful-javascript-and-jquery-tools-libraries-plugins" target="_blank">http://www.smashingmagazine.com/2011/04/07/useful-javascript-and-jquery-tools-libraries-plugins</a></li><li><a href="http://webdesigneraid.com/weekly-html5-news-and-inspirations-%E2%80%93-tutorials-tools-resources-and-freebies-v-2/" target="_blank">http://webdesigneraid.com/weekly-html5-news-and-inspirations-%E2%80%93-tutorials-tools-resources-and-freebies-v-2/</a></li><li><a href="http://www.designer-daily.com/15-useful-jquery-plugins-and-tutorials-5207" target="_blank">http://www.designer-daily.com/15-useful-jquery-plugins-and-tutorials-5207</a></li><li><a href="http://www.julien-verkest.fr/22/11/2007/240-plugins-jquery" target="_blank">http://www.julien-verkest.fr/22/11/2007/240-plugins-jquery</a></li><li><a href="http://www.hotscripts.com/blog/10-great-html5-experiments-apps/" target="_blank">http://www.hotscripts.com/blog/10-great-html5-experiments-apps/</a></li><li><a href="http://www.noupe.com/jquery/excellent-jquery-navigation-menu-tutorials.html" target="_blank">http://www.noupe.com/jquery/excellent-jquery-navigation-menu-tutorials.html</a></li><li><a href="http://www.noupe.com/php/20-useful-php-jquery-tutorials.html" target="_blank">http://www.noupe.com/php/20-useful-php-jquery-tutorials.html</a></li><li><a href="http://aext.net/2010/04/excellent-jquery-plugins-resources-for-data-presentation-and-grid-layout/" target="_blank">http://aext.net/2010/04/excellent-jquery-plugins-resources-for-data-presentation-and-grid-layout/</a></li><li><a href="http://webdesigneraid.com/html5-canvas-graphing-solutions-every-web-developers-must-know/" target="_blank">http://webdesigneraid.com/html5-canvas-graphing-solutions-every-web-developers-must-know/</a></li><li><a href="http://gestureworks.com/features/open-source-gestures/" target="_blank">http://gestureworks.com/features/open-source-gestures/</a></li><li><a href="http://edtechdev.wordpress.com/2011/01/14/some-exciting-new-html5javascript-projects/" target="_blank">http://edtechdev.wordpress.com/2011/01/14/some-exciting-new-html5javascript-projects/</a></li><li><a href="http://net.tutsplus.com/articles/web-roundups/30-developers-you-must-subscribe-to-as-a-javascript-junkie/" target="_blank">http://net.tutsplus.com/articles/web-roundups/30-developers-you-must-subscribe-to-as-a-javascript-junkie/</a></li></ul> <h4>HTML5 视频播放器</h4> <p><img title="leanBackPlayer" src="http://www.b2bweb.fr/wp-content/uploads/leanBackPlayer.jpg" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="https://github.com/webmademovies/popcorn-js" target="_blank"><strong>Popcorn.js</strong></a> 是一个HTML5 Video框架，它提供了易于使用的API来同步交互式内容，让操作HTML5 Video元素的属性，方法和事件变得简单易用。 (来自Mozilla)</li><li><a href="http://dev.mennerich.name/showroom/html5_video/" target="_blank"><strong>LeanBack Player</strong></a> HTML5视频播放器,没有依赖任何JavaScript框架。支持全屏播放，音量控制，在同一个页面中播放多个视频。 (来自Google)</li><li><a href="http://m.vid.ly/user/" target="_blank"><strong>Vid.ly</strong></a>   为你上传的视频提供转换功能，并且为转换后的视频创建一个短网址。通过Vid.ly，让你的视频可以在14种不同的浏览器和设备上播放，不需要再去考虑将  要浏览视频的人使用什么设备了，以避免各各软件巨头之间的利益之争带来了不兼容，给用户带来了巨大的困扰，短网址让你可以通过Twitter、  Facebook等方式方便分享视频。Vid.ly还可以通过html代码嵌入到其他网页中。Vid.ly免费帐户空间为1GB，免费帐户也没有播放或浏  览限制。</li></ul> <h4>JavaScript 音频处理与可视化效果</h4> <p><img title="soundmanager" src="http://www.b2bweb.fr/wp-content/uploads/soundmanager.png" alt="" height="238" width="600" /></p> <ul><li>&#9733; 使用HTML5 和 Flash,&nbsp;<a href="http://www.schillmania.com/projects/soundmanager2/" target="_blank"><strong>SoundManager V2</strong></a> 只用单一API的提供了可靠，简单和强大的跨平台的音频处理。</li><li><a href="https://github.com/corbanbrook/dsp.js/" target="_blank"><strong>DSP</strong></a>, JavaScript的声音Digital Signal Processing</li><li>The Radiolab&nbsp;<a href="http://yoyodyne.cc/radiolab/" target="_blank"><strong>Hyper Audio Player</strong></a> v1, 带给你 WNYC Radiolab, SoundCloud 和 Mozilla Drumbeat</li><li><a href="http://jplayer.org/" target="_blank"><strong>jPlayer</strong></a>, 一个 jQuery HTML5 音频/ 视频库，功能齐全的API</li></ul> <h4>JavaScript 图形 和 3D</h4> <p><img title="processing" src="http://www.b2bweb.fr/wp-content/uploads/processing.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://processingjs.org/" target="_blank"><strong>Processing.js</strong></a>是一个开放的编程语言，在不使用Flash或Java小程序的前提下, 可以实现程序图像、动画和互动的应用。其使用Web标准，无需任何插件。</li><li>&#9733; Javascript 3D 引擎:&nbsp;<a href="https://github.com/mrdoob/three.js" target="_blank"><strong>ThreeJS</strong></a> 由 Mr Doob 开发，一个轻量级的 3D 引擎，不需要了解细节，傻瓜都能使用。这个引擎可以使用&lt;canvas&gt;, &lt;svg&gt; 和 WebGL.</li><li><a href="http://www.iquilezles.org/apps/shadertoy/" target="_blank"><strong>Shader Toy</strong></a>, 一款使用WebGL的在线着色器编辑器(2D/3D). 基于在线的应用架构使您无需下载任何软件即可开始体验. Shader Toy包含大量实用着色器, 诸如光线追踪, 场景距离渲染, 球体, 隧道, 变形, 后期处理特效等.</li><li><a href="http://senchalabs.github.com/philogl/" target="_blank"><strong>PhiloGL</strong></a>, Sencha的PhiloGL是首个WebGL开发工具之一，提供了高水准的功能，来构建WebGL应用。Sencha创建了几个演示，来描述框架交互式3D虚拟化的能力，比如<a href="http://senchalabs.github.com/philogl/PhiloGL/examples/temperatureAnomalies/">3D view of global temperature changes</a>。</li><li><a href="http://benvanik.github.com/WebGL-Inspector/" target="_blank"><strong>WebGL Inspector</strong></a> 你就Firebug等Web调试工具一样，这个是 WebGL的调试工具。</li><li><a href="http://www.khronos.org/webgl/wiki_1_15/" target="_blank"><strong>WebGL frameworks</strong></a> 由 Khronos Group 收集的一个WebGL框架列表。</li><li><a href="http://easeljs.com/" target="_blank"><strong>EaselJS</strong></a>, 一个使用html5的canvas的 JavaScript 库.&nbsp;<a href="https://github.com/gskinner/EaselJS" target="_blank">Sources</a>.</li><li><a href="http://www.webresourcesdepot.com/free-javascript-game-frameworks-to-create-a-web-based-fun/" target="_blank"><strong>JavaScript Game Frameworks</strong></a> 免费的JS游戏框架列表。另，可参看 <a title="JS游戏引擎列表" href="http://coolshell.cn/articles/3516.html" target="_blank">JS游戏框架列表</a>。</li><li><a href="http://raphaeljs.com/" target="_blank"><strong>Rapha&#235;l</strong></a>是一个小型的JavaScript 库，用来简化在页面上显示向量图的工作。你可以用它在页面上绘制各种图表、并进行图片的剪切、旋转等操作。参看<a title="Javascript向量图Lib&#8211;Rapha&#235;l" href="http://coolshell.cn/articles/3107.html" target="_blank">Javascript向量图Lib&#8211;Rapha&#235;l</a></li><li><a href="http://keith-wood.name/svgRef.html" target="_blank"><strong>jQuery SVG</strong></a> 插件让你可以了 SVG canvas 进行交互。</li><li><a href="http://code.google.com/intl/fr/apis/chart/" target="_blank"><strong>Google chart tools</strong></a> &#8211; &nbsp;参看本站的<a href="http://coolshell.cn/articles/582.html" target="_blank">使用Google API做统计图</a></li><li><a href="http://arborjs.org/" target="_blank"><strong>Arbor.js</strong></a>,&nbsp;是一个利用webworkers和jQuery创建的数据图形可视化JavaScript框架。它为图形组织和屏幕刷新处理提供了一个高效、力导向布局算法。</li></ul> <h4>JavaScript 浏览器接口 (HTML5)</h4> <p><img title="amplify" src="http://www.b2bweb.fr/wp-content/uploads/amplify.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://www.modernizr.com/" target="_blank"><strong>Modernizr</strong></a> &#8211; 是一个专为HTML5 和CSS3 开发的功能检测类库，可以根据浏览器对HTML5 和CSS3 的支持程度提供更加便捷的前端优化方案.<a href="https://github.com/Modernizr/Modernizr" target="_blank">Sources</a>. 一个有用的列表&nbsp;<a href="https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills" target="_blank">cross-browser Polyfills</a></li><li><a href="http://code.google.com/p/html5shiv/" target="_blank"><strong>HTML5Shiv</strong></a> : 该项目的目的是为了让IE 能识别HTML5 的元素。</li><li><a href="https://github.com/remy/polyfills" target="_blank"><strong>Polyfills</strong></a> : 这个项目收集了一些代码片段其用Javascript支持不同的浏览器的特别功能，有些代码需要Flash。</li><li><a href="http://yepnopejs.com/" target="_blank"><strong>YepNopeJS</strong></a> : 一个异步的条件式的加载器。<a href="https://github.com/SlexAxton/yepnope.js" target="_blank">Sources</a>.</li><li>jQuery&nbsp;<a href="https://github.com/codler/jQuery-Css3-Finalize/" target="_blank"><strong>CSS3 Finalise</strong></a> : 是否厌倦了为每一个浏览器的CSS3属性加前缀？</li><li>&#9733;&nbsp;<a href="http://amplifyjs.com/" target="_blank"><strong>Amplify.js</strong></a> :一套用于web应用数据管理和应用程序通讯的<strong> jQuery 组件库</strong>。  提供简单易用的API接口。Amplify的目标是通过为各种数据源提供一个统一的程序接口简化各种格式数据的数据处理。Amplify的存储组件使用  localStorage 和   sessionStorage标准处理客户端的存储信息，对一些老的浏览器支持可能有问题。Amplify&#8217;为jQuery的ajax方法request  增加了一些额外的特性。&nbsp;<a href="https://github.com/appendto/amplify" target="_blank">Sources</a>.</li><li><a href="https://github.com/balupton/history.js" target="_blank"><strong>History.js</strong></a> 优美地支持了HTML5 History/State APIs</li><li><a href="http://socket.io/" target="_blank"><strong>Socket.IO</strong></a> Web的socket编程。</li></ul> <h4>JavaScript 工具</h4> <p><img title="headJs" src="http://www.b2bweb.fr/wp-content/uploads/headJs.png" alt="" height="238" width="600" /></p> <ul><li>&#9733; &nbsp;{{<a href="http://mustache.github.com/" target="_blank"><strong>mustaches</strong></a>}} 小型的 JavaScript 模板引擎。</li><li><a href="http://jsonselect.org/" target="_blank"><strong>json:select()</strong></a>, CSS式的JSON选择器</li><li><a href="http://headjs.com/" target="_blank"><strong>HeadJS</strong></a>, 异步JavaScript装载。其最大特点就是不仅可以按顺序执行还可以并发装载载js。</li><li><a href="http://code.google.com/p/jsdoc-toolkit/" target="_blank"><strong>JsDoc Toolkit</strong></a>是一款辅助工具，你只需要根据约定在JavaScript 代码中添加相应的注释，它就可以根据这些注释来自动生成API文档。</li><li><a href="https://github.com/filamentgroup/Responsive-Images" target="_blank"><strong>Responsive image</strong></a>, 一个试验性的项目，用来处理<a href="http://www.alistapart.com/articles/responsive-web-design/">responsive layouts</a> 式的图片。</li><li><a href="http://marijnhaverbeke.nl/uglifyjs" target="_blank"><strong>UglifyJS</strong></a>是基于NodeJS的Javascript语法解析/压缩/格式化工具，它支持任何CommonJS模块系统的Javascript平台。</li><li><a href="http://www.dhteumeuleu.com/" target="_blank"><strong>Dhteumeuleu</strong></a>, 交互式的 DOM 脚本和DHTML 的开源演示。</li><li><a href="https://github.com/documentcloud/backbone/" target="_blank"><strong>Backbone</strong></a>是  一个前端 JS 代码 MVC 框架，被著名的 37signals 用来构建他们的移动客户端。它不可取代   Jquery，不可取代现有的Template 库。而是和这些结合起来构建复杂的 web 前端交互应用。如果项目涉及大量的 javascript   代码，实现很多复杂的前端交互功能，首先你会想到把数据和展示分离。使用 Jquery 的 selector 和 callback   可以轻松做到这点。但是对于富客户端的WEB应用大量代码的结构化组织非常必要。Backbone 就提供了 javascript   代码的组织的功能。Backbone 主要包括 models, collections, views 和 events, controller 。</li></ul> <h4>客户端和模拟器</h4> <p><img title="firebug" src="http://www.b2bweb.fr/wp-content/uploads/firebug.png" alt="" height="238" width="600" /></p> <ul><li><a href="http://browsershots.org/" target="_blank"><strong>BrowserShot</strong></a>, 检查浏览器的兼容性，跨浏览器平器的测试</li><li><strong><a href="http://tester.jonasjohn.de/" target="_blank">Test everything</a></strong>&#8230; 输入一个你想要测试的URL&#8230;&#8230;</li><li><a href="http://tmobile.modeaondemand.com/htc/g1/" target="_blank"><strong>Android browser</strong></a> 模拟器</li><li><a href="http://iphonetester.com/" target="_blank"><strong>iPhone browser</strong></a> 模拟器</li><li><a href="http://www.opera.com/mobile/demo/" target="_blank"><strong>Opera browser</strong></a> 模拟器</li><li>&#9733;&nbsp;<a href="http://getfirebug.com/whatisfirebug" target="_blank"><strong>Firebug</strong></a> 与&nbsp;<strong><a href="http://www.mozilla.com/fr/firefox/" target="_blank">Firefox</a></strong> 集成，可以查看和调试你的Web页面。</li></ul> <h3>CSS3 和 字库</h3> <p><img title="patternTap" src="http://www.b2bweb.fr/wp-content/uploads/patternTap.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://www.css3maker.com/" target="_blank"><strong>CSS3 Maker</strong></a> CCS3的生成器</li><li>容易地创建&nbsp;<strong><a href="http://www.sencha.com/products/animator/" target="_blank">CSS3 animations</a>。</strong> Sencha Animator 是一个桌面应用可以为WebKit浏览器和触摸式移动设备创建 CSS3 animations 。</li><li><a href="http://csswarp.eleqtriq.com/" target="_blank"><strong>CSSwarp</strong></a> &#8211; CSS 文本扭曲生成器</li><li><a href="http://www.colorzilla.com/gradient-editor/" target="_blank"><strong>Gradient Editor</strong></a>, 一个强大的Photoshop式的CSS 渐变编译器。来自 ColorZilla</li><li>&#9733;&nbsp;<a href="http://www.google.com/webfonts" target="_blank"><strong>Google Web Fonts</strong></a> 通过Google Web Fonts API 可以浏览所有的字体</li><li><a href="http://www.fontsquirrel.com/fontface/generator" target="_blank"><strong>@font-face Kit Generator</strong></a>, 为Web转换字体</li><li><a href="http://www.typetester.org/" target="_blank"><strong>Typetester</strong></a>, 比较字体。</li><li><a href="http://mediaqueri.es/" target="_blank"><strong>Media Queries</strong></a>. 一组 responsive web 设计。</li><li><a href="http://patterntap.com/" target="_blank"><strong>Pattern TAP</strong></a>, UI组件。</li></ul> <h4>Website (FULL) 模板</h4> <p><img title="boilerplate" src="http://www.b2bweb.fr/wp-content/uploads/boilerplate1.png" alt="" height="238" width="600" /></p> <ul><li>&#9733;&nbsp;<a href="http://html5boilerplate.com/" target="_blank"><strong>HTML5 Boilerplate</strong></a> 是一个<a href="http://www.mhtml5.com/">HTML5 </a>/ CSS / js模板，是实现跨浏览器正常化、性能优化，稳定的可选功能如跨域Ajax和Flash的最佳实践。 项目的开发商称之为技巧集合，目的是满足您开发一个跨浏览器，并且面向未来的网站的需求。&nbsp;<a href="https://github.com/paulirish/html5-boilerplate" target="_blank">Sources</a>.</li><li><a href="http://sickdesigner.com/resources/HTML5-starter-pack/" target="_blank"><strong>HTML5 starter pack</strong></a> 是一个干净的和有组织的目录结构，其可适合很多项目，还有一些很常用的文件，以及简单的Photoshop设计模板。</li><li>&#9733;&nbsp;<a href="http://initializr.com/" target="_blank"><strong>Initializr</strong></a> 是一个HTML5 模板生成器，其可以帮你在15秒内创建一个HTML5的项目。</li><li><a href="http://tympanus.net/Tutorials/AnimatedPortfolioGallery/" target="_blank"><strong>Animated Portfolio Gallery</strong></a> （<a href="http://tympanus.net/codrops/2010/11/14/animated-portfolio-gallery/" target="_blank">教程</a>）</li><li> <a href="http://tutorialzine.com/2010/07/making-slick-mobileapp-website-jquery-css/" target="_blank"><strong>Slick MobileApp Website</strong></a> 如果通过 jQuery 和 CSS 制作一个手机应用的网站。</li><li> <a href="http://net.tutsplus.com/tutorials/javascript-ajax/how-to-build-an-rss-reader-with-jquery-mobile-2/" target="_blank"><strong>RSS Reader</strong></a> 如果通过 jQuery Mobile 创建一个RSS Reader</li><li>&#9733; <a href="http://addyosmani.com/blog/building-spas-jquerys-best-friends/" target="_blank"><strong>Single Page Applications</strong></a> 使用jQuery的朋友们 (Backbone, Underscore, &#8230;)创建单一页面。</li><li><a href="http://code.google.com/p/gtv-resources/" target="_blank"><strong>Google TV Optimized Templates</strong></a>, 传统电视已经开始和网路融合，但现阶段产业仍然正在摸索之中，为此将来的网页亦会有结构上的改变。<a href="http://code.google.com/p/gtv-resources/">Google TV Optimized Templates</a>是  一个用HTML/JavaScript制成的开源软体，一如其名是一个对Google   TV作出了最佳化的的网页范本，其特色是以遥控器作为操作的前提，令使用者无需输入任何文字就可以进行控制。未来除了会有专用遥控器外，还会采用智能手机  透过W-iFi控制Google TV的方法。Optimized   Templates的界面中左方会展示分类，右方会显示该分类下的影片截图，影片播放、切换、全画面表示都可透过键盘上的方向键、Backspace或  Enter等键完成，方便今后的网站开发人员借镜。HTML5 版的模板使用了&nbsp;<a href="http://code.google.com/p/gtv-ui-lib" target="_blank">Google TV UI library</a>, jQuery &nbsp;和 Closure 。</li></ul> <p>（全文完）</p></div><img src ="http://www.blogjava.net/jelver/aggbug/352472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2011-06-17 07:58 <a href="http://www.blogjava.net/jelver/articles/352472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中传输对象时候的问题（转）</title><link>http://www.blogjava.net/jelver/articles/350367.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 17 May 2011 00:39:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/350367.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/350367.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/350367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/350367.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/350367.html</trackback:ping><description><![CDATA[<table style="table-layout: fixed; width: 100%;"> <tbody> <tr> <td><div id="blog_text"> <p>对于同一个socket，如果调用两次就会抛出StreamCorruptedException</p> <p>如果你使用socket，并通过对象输入/输出流来处理的话，并且已经对某个socket调用了一次getInputStream时，但又需要把这个socket的相关信息作为参数传递给别的对象时，应注意：不用直接把socket传过去，应该把对应的ObjectInputStream或ObjectOutputStream对象传递过去。</p> <p>调用getInputStream方法就会读取标示头信息。用缺省的serializetion的实现时,一个ObjectOutputStream的构造和一个ObjectInputStream的构造必须一一对应.ObjectOutputStream的构造函数会向输出流中写入一个标识头,而ObjectInputStream会首先读入这个标识头.因此,多次以追加方式向一个文件中写入object时,该文件将会包含多个标识头.所以用ObjectInputStream来deserialize这个ObjectOutputStream时,将产生StreamCorruptedException.</p> <p><br />==============================</p> <p>使用ObjectStream会出现的问题</p> <p>1.  ObjectInputStream与ObjectOutputStream的顺序问题<br />在网络通讯中，主机与客户端若使用ObjectInputStream与ObjectOutputStream建立对象通讯，必须注意声明此两个对象的顺序。<br />如：<br />主机端先建立ObjectInputStream后建立ObjectOutputStream，则对应地客户端要先建立ObjectOutputStream后建立ObjectInputStream，否则会造成两方互相等待数据而导致死锁。<br />原因是建立ObjectInputStream对象是需要先接收一定的header数据，接收到这些数据之前会处于阻塞状态。以下为JAVA  API文档的说明<br />Creates an ObjectInputStream that reads from the specified  InputStream.<br />A serialization stream header is read from the stream and  verified.<br />This constructor will block until the corresponding  ObjectOutputStream<br />has written and flushed the header.</p> <p>故而为了防止这种死锁状态，通讯两方的ObjectInputStraem,ObjectOutputStream必须注意顺序对应使用。</p> <p>2.  ObjectInputStream接收到非ObjectOutputStream数据的问题<br />在使用ObjectInputStream与ObjectOutputStream对象通讯的通讯双方，假设客户端程序出现错误，发送了非ObjectOutputStream封装发送的数据（比如发送一个数字或字符串到主机），则主机端的ObjectInputStream接收到错误数据后不能自动纠正，会一直接收数据而处于阻塞状态，从而导致通讯失败。尚未找到解决方法。目前想的办法为写自己的ObjectStream类。</p> <p>3. 解决版本问题<br />使用ObjectStream的时候会额外发送一个关于对象的序列号<br />static final long  serialVersionUID =  ....<br />手动加入此域则可避免版本差异导致的问题。<br />对象序列号的计算可用SDK的serialver计算。</p> <p>======================================</p> <p>ObjectInputStream ObjectOutputStream</p> <p>ObjectOutputStream和ObjectInputStream</p> <p>--ObjectOutputStream</p> <p>ObjectInputStream 类恢复以前使用 ObjectOutputStream 类序列化后的基本类型数据和对象。</p> <p>ObjectOutputStream 和 ObjectInputStream 分别利用 FileOutputStream 和  FileInputStream 能支持应用程序实现对象图象的稳定存储。</p> <p>ObjectInputStream 可用于恢复以前序列化过的对象。另外其它一些情况也使用此类，诸如使用一个 Socket 在主机间传递对象时，</p> <p>或在远程通讯系统中为实现参数和参变量的通讯而进行对象传递时。</p> <p>ObjectInputStream 保证从流中创建的图象中的所有对象的类型与 Java 虚拟机中出现的类匹配。使用标准机制按需装载相应类。</p> <p>只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流中读取。使用 readObject  方法从该流中</p> <p>读取一个对象。 Java 的安全造型应该用于获取期望类型。在 Java 中, 串和数组都是对象且可当作是序列化过程中的对象。</p> <p>读取时，它们需要转换为所需类型。</p> <p>另外基类型也可使用 DataInput 中的正确方法从该流中读取。</p> <p>对象的缺省逆序列化机制将每个域的内容恢复为它被写入时的值和类型。逆序列化过程中忽略申明为暂时的或静态的域。</p> <p>对其它对象的引用促使那些对象必须从流中读取。使用引用共享机制正确地恢复对象的图象。逆序列化时总是分配新对象，</p> <p>防止重写已存在的对象。</p> <p>读取一个对象同运行一个新对象的构造子类似。为该对象分配的内存初始化为空(NULL)。为非序列化类调用无参构造子，</p> <p>然后将序列化类的域从该流中恢复，恢复从最接近 java.lang.object 的序列化对象开始，到指定对象结束。</p> <p>例如读取在示例中写入 ObjectOutputStream 中的流：</p> <p><br />FileInputStream istream = new  FileInputStream("t.tmp");<br />ObjectInputStream p = new  ObjectInputStream(istream);<br />int i = p.readInt();<br />String today =  (String)p.readObject();<br />Date date =  (Date)p.readObject();<br />istream.close();<br /><br />类通过实现 java.io.Serializable 或  java.io.Externalizable 接口来控制它们的序列化。</p> <p>实现序列化接口可以使对象能保存和恢复它的完整状态，可以使类在写入流和从流中读取的期间内进行改进。</p> <p>它自动地遍历对象间的引用，保存和恢复完整图象。在序列化和逆序列化处理过程中需要特定句柄的可序列化类，</p> <p>必须实现如下这两个方法：</p> <p><br />private void writeObject(java.io.ObjectOutputStream stream)<br />&nbsp;&nbsp;&nbsp;&nbsp;  throws IOException;<br />private void readObject(java.io.ObjectInputStream  stream)<br />&nbsp;&nbsp;&nbsp;&nbsp; throws IOException, ClassNotFoundException; <br /><br />利用  writeObjectmethod 方法将一个特殊类的对象的状态写入某流后，相应的 readObject 方法将负责读取和恢复这些数据。</p> <p>此方法不必关心状态是属于它的父类还是子类。 从 ObjectInputStream 读取数据恢复单个域的状态，并将之赋给该对象的恰当域。</p> <p>使用 DataInput 方法读取基本数据类型。</p> <p>序列化操作对没有实现 java.io.Serializable 接口的对象，不读取或分配它的域值。非序列化对象的子类可以是序列化的。</p> <p>在这种情况下，非序列化类必须有一个无参构造子，使它的域能使用此构造子完成初始化。 在此情况下，</p> <p>子类负责保存和恢复非序列化类的状态。通常情况父类的域是可存储的(公有的、包或保护的)，</p> <p>或存在用于恢复它的状态的可使用的获取或设置方法。</p> <p>ObjectInputStream 能获取逆序列化一个对象期间出现的任一异常，一旦出现异常，则放弃读过程。</p> <p>实现外部接口可以使对象完全控制此对象序列化形式的内容和格式。</p> <p>调用外部接口的方法：writeExternal 和 readExternal 保存和恢复对象状态。当一个类实现了这些方法时，</p> <p>它们就能使用 ObjectOutput 和 ObjectInput 方法的所有方法写入或读取它们自己的状态。对象负责管理它出现的相应版本。</p> <p><br />ObjectOutputStream</p> <p>public class ObjectOutputStream <br />extends OutputStream <br />implements  ObjectOutput, ObjectStreamConstants <br />类 ObjectOutputStream 将 Java  对象中的基本数据类型和图元写入到一个 OutputStream 对象中。可使用 ObjectInputStream 读取这些对象。</p> <p>另外使用此流对应的文件能存储这些对象。如果该流是一个网络通讯流，则在另一台主机或另一个处理机上可重建这些对象。</p> <p>只有支持 java.io.Serializable 接口的对象才能被写入该流。对每个可序列化的对象进行编码，包括相应类的名称和标记，</p> <p>对象的属性和数组值，以及初始化对象时引用的任何其它对象等。</p> <p>使用 writeObject 将一个对象写入该流。任一对象，包括串和数组，均采用 writeObject 方法被写入。</p> <p>也能将多个对象或基类型对象写入此流。反过来，必须以这些对象被写入的相同类型和相同顺序，</p> <p>从相应的 ObjectInputstream 流中读回这些对象。</p> <p>基类型也可使用 DataOutput 中的正确方法写入此流。串对象也可使用 writeUTF 方法写入。</p> <p>一个对象的缺省序列化机制将写入对象的类，类标记和所有的非暂时的和非静态的属性值。</p> <p>其它对象(除暂时的或静态的属性)的引用也将促使以上这些对象被写入。 使用共享机制，对单一对象的多次引用进行编码，</p> <p>以至对象的图元能被存储为与它原来写入时有相同的形状。</p> <p>例如写入一个对象，此对象能从 ObjectInputStream 中读出：</p> <p><br />FileOutputStream ostream = new  FileOutputStream("t.tmp");<br />ObjectOutputStream p = new  ObjectOutputStream(ostream);<br />p.writeInt(12345);<br />p.writeObject("Today");<br />p.writeObject(new  Date());<br />p.flush();<br />ostream.close();<br /><br />在序列化处理过程中需要特定句柄的类，必须使用如下这些恰当的标记实现特定的方法：</p> <p>private void readObject(java.io.ObjectInputStream stream)<br />&nbsp;&nbsp;&nbsp;&nbsp; throws  IOException, ClassNotFoundException; <br />private void  writeObject(java.io.ObjectOutputStream stream)<br />&nbsp;&nbsp;&nbsp;&nbsp; throws  IOException<br /><br />writeObject 方法负责写特定类的对象的状态，以使相应的 readObject 方法能存储它。</p> <p>此方法不必关心写入对象的父类或子类的状态。使用 writeObject 方法或基本类型支持的 DataOutput</p> <p>方法将每个域的状态保存到 ObjectOutputStream 中。</p> <p>序列化操作不能输出没有实现 java.io.Serializable 接口的任一对象的域。非序列化对象的子类可以是序列化的。</p> <p>在这种情况下，非序列化类必须有一个无参构造子，使它的域能被初始化。 在此情况下，子类负责保存和恢复非序列化类的状态。</p> <p>通常情况父类的域是可存储的(公有的、包或保护的)，或存在用于恢复它的状态的可使用的获取或设置方法。</p> <p>实现抛出 NotSerializableException 异常的 writeObject 和 readObject 方法能阻止一个对象的序列化。</p> <p>ObjectOutputStream 将获取这个异常，并放弃这个序列化过程。实现外部接口可以使对象完全控制此对象序列化形式的内容和格式。</p> <p>调用外部接口的方法：writeExternal 和 readExternal 保存和恢复对象状态。当一个类实现了这些方法时，</p> <p>它们就能使用 ObjectOutput 和 ObjectInput 方法的所有方法写入或读取它们自己的状态。对象负责管理它出现的相应版本。</p> <p><br />import java.io.*;<br />import java.util.*;</p> <p>public class Logon implements Serializable {</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Date date = new Date();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String  username;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private transient String password;</p> <p><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Logon(String name, String pwd) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; username =  name;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; password = pwd;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p> <p><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String toString() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pwd = (password  == null) ? "(n/a)" : password;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "logon info: \n " +  "username: " + username + "\n date: " + date + "\n password: " + pwd;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }</p> <p><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws IOException,  ClassNotFoundException {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Logon a = new Logon("Morgan",  "morgan83");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( "logon a = " +  a);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream o = new ObjectOutputStream( new  FileOutputStream("Logon.out"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  o.writeObject(a);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o.close();</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int seconds = 5;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long t =  System.currentTimeMillis() + seconds * 1000;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  while(System.currentTimeMillis() &lt; t) ;</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream in = new ObjectInputStream( new  FileInputStream("Logon.out"));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( "Recovering  object at " + new Date());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a =  (Logon)in.readObject();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("logon a = " + a);  <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />}<br /></p> <p>类Logon是一个记录登录信息的类，包括用户名和密码。首先它实现了接口Serializable，这就标志着它可以被序列化。</p> <p>之后再main方法里ObjectOutputStream o = new ObjectOutputStream( new  FileOutputStream("Logon.out"));</p> <p>新建一个对象输出流包装一个文件流，表示对象序列化的目的地是文件Logon.out。然后用方法writeObject开始写入。</p> <p>想要还原的时候也很简单ObjectInputStream in = new ObjectInputStream( new  FileInputStream("Logon.out"));</p> <p>新建一个对象输入流以文件流Logon.out为参数，之后调用readObject方法就可以了。</p></div></td></tr></tbody></table><img src ="http://www.blogjava.net/jelver/aggbug/350367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2011-05-17 08:39 <a href="http://www.blogjava.net/jelver/articles/350367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Float类型 减法运算时精度丢失问题</title><link>http://www.blogjava.net/jelver/articles/340038.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Wed, 08 Dec 2010 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/340038.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/340038.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/340038.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/340038.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/340038.html</trackback:ping><description><![CDATA[<table style="width: 100%; table-layout: fixed;" class="FCK__ShowTableBorders">
    <tbody>
        <tr>
            <td>
            <div>
            <p align="left"><font size="3">package test1;</font></p>
            <p align="left"><font size="3">public class Test2 {</font></p>
            <p align="left"><font size="3">/**<br />
            * @param args<br />
            */<br />
            public static void main(String[] args) {<br />
            &nbsp;&nbsp;  Float xx = 2.0f;<br />
            &nbsp;&nbsp;  Float yy = 1.8f;<br />
            &nbsp;&nbsp;  Float tt = xx - yy;<br />
            &nbsp;&nbsp;  System.out.println("tttttt-----" + tt);<br />
            <br />
            }</font></p>
            <p align="left"><font size="3">}</font></p>
            <p align="left"><font size="3">果然输出结果是: tttttt-----0.20000005</font></p>
            <p align="left"><font size="3">再测试了几个float类型的减法，除了*.0这样的相减没有异议之外，都存在这个问题，就是说float在相减的时候精度丢失了。后来在网上找到一段解决这个问题的办法，记在这里：</font></p>
            <p align="left"><font size="3">package test1;</font></p>
            <p align="left"><font size="3">import java.math.BigDecimal;</font></p>
            <p align="left"><font size="3">public class Test2 {</font></p>
            <p align="left"><font size="3">/**<br />
            * @param args<br />
            */<br />
            public static void main(String[] args) {<br />
            &nbsp;&nbsp;  Float xx = 2.2f;<br />
            &nbsp;&nbsp;  Float yy = 2.0f;<br />
            &nbsp;&nbsp;  Float tt = xx - yy;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;  </font><font size="3"><font style="background-color: #ff9900;">BigDecimal b1 = new BigDecimal(Float.toString(xx));<br />
            &nbsp;&nbsp;  BigDecimal b2 = new BigDecimal(Float.toString(yy));<br />
            &nbsp;&nbsp;  float ss = b1.subtract(b2).floatValue(); <br />
            </font>&nbsp;&nbsp;  System.out.println("ssss----" + ss);<br />
            &nbsp;&nbsp;  System.out.println("tttttt-----" + tt);<br />
            }<br />
            }<br />
            输出为:</font></p>
            <p align="left"><font size="3">ssss----0.2<br />
            tttttt-----0.20000005</font></p>
            <p align="left"><font size="3">这样一对比，差异就很明显了。</font></p>
            <p align="left"><font size="3">解决了问题，再找了一下为什么会产生这种差异：</font></p>
            <p align="left"><font size="3">网上有篇文章写得很详细，标题为《<font style="background-color: #ff0000;" color="#000000">剖析float型的内存存储和精度丢失问题</font>》，全文内容如下：</font></p>
            <p align="left"><span style="color: #ff0000; font-size: small;"><strong>问题提出：12.0f-11.9f=0.10000038，"减不尽"为什么？</strong> </span></p>
            <p align="left"><span style="font-size: small;">现在我们就详细剖析一下浮点型运算为什么会造成精度丢失？</span></p>
            <p align="left"><strong><span style="color: #800000; font-size: small;">1、小数的二进制表示问题</span></strong></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <span style="font-size: small;">首先我们要搞清楚下面两个问题：</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;  (1) 十进制整数如何转化为二进制数</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  算法很简单。举个例子，11表示成二进制数：</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  11/2=5 余&nbsp;&nbsp;  1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  5/2=2&nbsp;&nbsp;  余&nbsp;&nbsp;  1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  2/2=1&nbsp;&nbsp;  余&nbsp;&nbsp;  0</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  1/2=0&nbsp;&nbsp;  余&nbsp;&nbsp;  1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0结束&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  11二进制表示为(从下往上):1011</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  这里提一点：只要遇到除以后的结果为0了就结束了，大家想一想，所有的整数除以2是不是一定能够最终得到0。换句话说，所有的整数转变为二进制数的算法会不会无限循环下去呢？绝对不会，<strong><span style="color: #800000;">整数永远可以用二进制精确表示</span> </strong>，但小数就不一定了。</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (2) 十进制小数如何转化为二进制数</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  算法是乘以2直到没有了小数为止。举个例子，0.9表示成二进制数</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.9*2=1.8&nbsp;&nbsp;  取整数部分 1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.8(1.8的小数部分)*2=1.6&nbsp;&nbsp;&nbsp;  取整数部分 1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.6*2=1.2&nbsp;&nbsp;  取整数部分 1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.2*2=0.4&nbsp;&nbsp;  取整数部分 0</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.4*2=0.8&nbsp;&nbsp;  取整数部分 0</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.8*2=1.6 取整数部分 1</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.6*2=1.2&nbsp;&nbsp;  取整数部分 0</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  .........&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0.9二进制表示为(从上往下): 1100100100100......<br />
            </span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  注意：上面的计算过程循环了，也就是说*2永远不可能消灭小数部分，这样算法将无限下去。很显然，<strong><span style="color: #800000;">小数的二进制表示有时是不可能精确的</span> </strong>。其实道理很简单，十进制系统中能不能准确表示出1/3呢？同样二进制系统也无法准确表示1/10。这也就解释了为什么浮点型减法出现了"减不尽"的精度丢失问题。</span></p>
            <p align="left"><span style="font-size: small;"><strong><span style="color: #800000;">2、</span> </strong><strong><span style="color: #800000;">float型在内存中的存储</span> </strong><br />
            </span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;  众所周知、 <span style="font-size: small;">Java 的float型在内存中占4个字节。float的32个二进制位结构如下</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
            <p align="left"><strong><span style="color: #0000ff; font-size: small;">float内存存储结构</span><span style="color: #0000ff; font-size: small;"><br />
            </span></strong></p>
            <p align="left"><strong><span style="color: #0000ff; font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  4bytes &nbsp;&nbsp;&nbsp;&nbsp;  31 &nbsp;&nbsp;  30 &nbsp;&nbsp;  29----23 &nbsp;&nbsp;  22----0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span></strong></p>
            <p align="left"><strong><font size="3"><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color: #0000ff; font-size: small;">表示&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  实数符号位 &nbsp;&nbsp;  指数符号位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  指数位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  有效数位</span> </font></strong></p>
            <p align="left"><strong><span style="color: #0000ff; font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  其中符号位1表示正，0表示负。有效位数位24位，其中一位是实数符号位。</span></strong></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;</span><font size="3"> &nbsp;&nbsp;&nbsp;&nbsp;  <strong><span style="color: #ff9900; font-size: small;">将一个float型转化为内存存储格式的步骤为： </span></strong></font></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><span style="color: #800000; font-size: small;"><span style="color: #ff6600;">（1）先将这个实数的绝对值化为二进制格式，注意实数的整数部分和小数部分的二进制方法在上面已经探讨过了。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （2）将这个二进制格式实数的小数点左移或右移n位，直到小数点移动到第一个有效数字的右边。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （3）从小数点右边第一位开始数出二十三位数字放入第22到第0位。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （4）如果实数是正的，则在第31位放入&#8220;0&#8221;，否则放入&#8220;1&#8221;。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （5）如果n 是左移得到的，说明指数是正的，第30位放入&#8220;1&#8221;。如果n是右移得到的或n=0，则第30位放入&#8220;0&#8221;。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （6）如果n是左移得到的，则将n减去1后化为二进制，并在左边加&#8220;0&#8221;补足七位，放入第29到第23位。如果n是右移得到的或n=0，则将n化为二进制后在左边加&#8220;0&#8221;补足七位，再各位求反，再放入第29到第23位。</span> </span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;  <span style="font-size: small;">举例说明： 11.9的内存存储格式</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (1) 将11.9化为二进制后大约是"</span><font size="3"> <span style="font-size: small;">1011<strong>.</strong> </span><span style="font-size: small;">1110011001100110011001100..."。</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (2) 将小数点左移三位到第一个有效位右侧： </span><span style="font-size: small;">"1<strong>.</strong> 011</span><font size="3"> <span style="font-size: small;">11100110011001100110</span> <span style="font-size: small;">"。</span> <span style="font-size: small;">保证有效位数24位，右侧多余的截取（<span style="color: #ff0000;"><strong>误差在这里产生了</strong> </span>）。</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (3) </span><span style="font-size: small;">这已经有了二十四位有效数字，将最左边一位&#8220;1&#8221;去掉，得到&#8220;</span><font size="3"> <span style="font-size: small;">011</span> <span style="font-size: small;">11100110011001100110</span> <span style="font-size: small;">&#8221;共23bit。将它放入float存储结构的第22到第0位。</span></font></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (4) 因为11.9是正数，因此在第31位实数符号位放入&#8220;0&#8221;。 </span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (5) 由于我们把小数点左移，因此在第30位指数符号位放入&#8220;1&#8221;。</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  (6) 因为我们是把小数点左移3位，因此将3减去1得2，化为二进制，并补足7位得到0000010，放入第29到第23位。 </span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后表示11.9为： <span style="color: #0000ff;">0 <span style="color: #ff9900;">1</span> </span><span style="color: #008000;">0000010 </span><span style="font-size: small;">011</span> <span style="font-size: small;">11100110011001100110</span></font></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </font><span style="font-size: small;">再举一个例子：0.2356的内存存储格式<br />
            &nbsp;&nbsp;  &nbsp;&nbsp;  （1）将0.2356化为二进制后大约是0.00111100010100000100100000。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  （2）将小数点右移三位得到1.11100010100000100100000。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  （3）从小数点右边数出二十三位有效数字，即11100010100000100100000放<br />
            入第22到第0位。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  （4）由于0.2356是正的，所以在第31位放入&#8220;0&#8221;。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  （5）由于我们把小数点右移了，所以在第30位放入&#8220;0&#8221;。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  （6）因为小数点被右移了3位，所以将3化为二进制，在左边补&#8220;0&#8221;补足七<br />
            位，得到0000011，各位取反，得到1111100，放入第29到第23位。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <span style="font-size: small;">最后表示0.2356为：<span style="color: #0000ff;">0</span> <span style="color: #ff9900;">0</span> <span style="color: #008080;">1111100</span> 11100010100000100100000</span></font></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span><font size="3"><strong>将一个内存存储的float二进制格式转化为十进制的步骤：</strong> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （1）将第22位到第0位的二进制数写出来，在最左边补一位&#8220;1&#8221;，得到二十四位有效数字。将小数点点在最左边那个&#8220;1&#8221;的右边。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （2）取出第29到第23位所表示的值n。当30位是&#8220;0&#8221;时将n各位求反。当30位是&#8220;1&#8221;时将n增1。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （3）将小数点左移n位（当30位是&#8220;0&#8221;时）或右移n位（当30位是&#8220;1&#8221;时），得到一个二进制表示的实数。 <br />
            &nbsp;&nbsp;&nbsp;&nbsp;  （4）将这个二进制实数化为十进制，并根据第31位是&#8220;0&#8221;还是&#8220;1&#8221;加上正号或负号即可。</font></span></p>
            <p align="left"><strong><font size="3"><span style="color: #800000;">3、浮点型的减法运算 </span></font></strong></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span><font size="3">浮点加减运算过程比定点运算过程复杂。<span>完成浮点加减运算的操作过程大体分为四步： <br />
            <span style="color: #ff0000;">  <span style="color: #ff6600;">(1) 0操作数的检查；</span> </span></span></font></span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><span><span style="color: #ff0000;"><span style="color: #ff6600;"><font size="3"><span style="background-color: #ffffff; color: #000000;">如果判断两个需要加减的浮点数有一个为0，即可得知运算结果而没有必要再进行有序的一些列操作。 <br />
            </span></font></span></span></span></p>
            <p align="left"><span style="color: #ff0000;"><font size="3"><span style="color: #ff6600;">   (2) 比较阶码（指数位）大小并完成对阶； </span></font></span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <span style="font-size: small;">两浮点数进行加减，首先要看两数的 </span><strong>指数位 </strong><span style="font-size: small;">是否相同，即小数点位置是否对齐。若两数 </span>指数位 <span style="font-size: small;">相同，表示小数点是对齐的，就可以进行尾数的加减运算。反之，若两数阶码不同，表示小数点位置没有对齐，此时必须使两数的阶码相同，这个过程叫做<span style="color: #ff0000;"><strong>对阶</strong> 。</span> </span></font></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #000000; font-size: small;">如何对</span> <span style="color: #000000; font-size: small;">阶(假设两浮点数的指数位为 </span><span style="font-size: small;">E<em><sub>x</sub></em> 和 E<em><sub>y</sub></em> </span><span style="color: #000000; font-size: small;">)： </span></font></p>
            <p align="left"><font size="3"><span style="color: #ff0000;"><span style="color: #ff6600;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span></span><span style="font-size: small;">通过尾数的移位以改变 E<em><sub>x</sub></em> 或 E<em><sub>y</sub></em> ，使之相等。 <span>由
            于浮点表示的数多是规格化的，尾数左移会引起最高有位的丢失，造成很大误差；而尾数右移虽引起最低有效位的丢失，但造成的误差较小，因此，对阶操作规定使
            尾数右移，尾数右移后使阶码作相应增加，其数值保持不变。很显然，一个增加后的阶码与另一个相等，所增加的阶码一定是小阶。因此在对阶时，总是使<span style="color: #ff0000;"><strong>小阶向大阶看齐</strong> </span>，即小阶的尾数向右移位</span> ( 相当于小数点左移 ) ，每右移一位，其阶码加 1 ，直到两数的阶码相等为止，右移的位数等于阶差 △ <sub>E </sub>。 </span><br />
            <span style="color: #ff0000;"><span style="color: #ff6600;">   (3) 尾数（有效数位）进行加或减运算； </span></span></font></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  对阶完毕后就可 有效数位 求和。 不论是加法运算还是减法运算，都按加法进行操作，其方法与定点加减运算完全一样。 </font><span><span><span style="color: #ff0000;"><span style="color: #ff6600;"><br />
            <font size="3">   (4) 结果规格化并进行舍入处理。</font></span></span></span></span></p>
            <p align="left"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <span style="font-size: small;">略</span></font></p>
            <span style="font-size: small;">
            <p align="left"><span style="color: #800000;"><strong>4、 计算12.0f-11.9f </strong></span></p>
            <p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <span style="font-size: small;">12.0f 的内存存储格式为： </span><span style="color: #0000ff; font-size: small;">0 </span><span style="color: #ff9900;">1 </span><span style="color: #008000;">0000010 </span><span style="font-size: small;">10000000000000000000000 &nbsp;&nbsp;&nbsp;  </span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;  11.9f 的内存存储格式为:&nbsp;&nbsp;  </span><span style="color: #0000ff; font-size: small;">0 </span><span style="color: #ff9900;">1 </span><span style="color: #008000;">0000010 </span><span style="font-size: small;">011</span> <span style="font-size: small;">11100110011001100110</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;  可见两数的指数位完全相同，只要对有效数位进行减法即可。</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;  12.0f-11.9f&nbsp;&nbsp;  结果：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span><span style="color: #0000ff; font-size: small;">0 </span><span style="color: #ff9900;">1 </span><span style="color: #008000;">0000010 </span><span style="font-size: small;">00000011001100110011010</span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  </span></p>
            <p align="left"><span style="font-size: small;">&nbsp;&nbsp;&nbsp;&nbsp;  将结果还原为十进制为： 0.000</span> <span style="font-size: small;">11001100110011010=</span> <span style="color: #ff0000; font-size: small;"><strong>0.10000038</strong> </span></p>
            </span></div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/jelver/aggbug/340038.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2010-12-08 10:02 <a href="http://www.blogjava.net/jelver/articles/340038.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ConcurrentHashMap原理分析</title><link>http://www.blogjava.net/jelver/articles/339963.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 07 Dec 2010 02:50:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/339963.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/339963.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/339963.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/339963.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/339963.html</trackback:ping><description><![CDATA[<h2><br />
</h2>
<h2><a href="http://geeklu.com/2010/07/concurrenthashmap/">ConcurrentHashMap原理分析</a></h2>
<br />
<div>
<p><img src="http://geeklu.com/wp-content/uploads/2010/07/Thread-300x238.gif" alt="" title="Thread" class="alignnone size-medium wp-image-30886" width="300" height="238" /></p>
</div>
<span id="Java">
<h2>一.Java并发基础</h2>
</span>
<p>当一个对象或变量可以被多个线程共享的时候，就有可能使得程序的逻辑出现问题。<br />
在一个对象中有一个变量i=0，有两个线程A，B都想对i加1，这个时候便有问题显现出来，关键就是对i加1的这个过程不是原子操作。要想对i进行递增，
第一步就是获取i的值，当A获取i的值为0，在A将新的值写入A之前，B也获取了A的值0，然后A写入，i变成1，然后B也写入i，i这个时候依然是1.<br />
当然java的内存模型没有上面这么简单，在Java Memory Model中，Memory分为两类，<br />
<img src="http://geeklu.com/wp-content/uploads/2010/07/jmm.png" alt="" title="jmm" class="alignnone size-full wp-image-30890" width="329" height="122" /><br />
main memory和working memory，main memory为所有线程共享，working
memory中存放的是线程所需要的变量的拷贝（线程要对main memory中的内容进行操作的话，首先需要拷贝到自己的working
memory，一般为了速度，working
memory一般是在cpu的cache中的）。volatile的变量在被操作的时候不会产生working
memory的拷贝，而是直接操作main
memory，当然volatile虽然解决了变量的可见性问题，但没有解决变量操作的原子性的问题，这个还需要synchronized或者CAS相关
操作配合进行。</p>
<p>多线程中几个重要的概念:</p>
<span id="">
<h4>可见性</h4>
</span>
<p>也就说假设一个对象中有一个变量i，那么i是保存在main memory中的，当某一个线程要操作i的时候，首先需要从main
memory中将i 加载到这个线程的working memory中，这个时候working
memory中就有了一个i的拷贝，这个时候此线程对i的修改都在其working memory中，直到其将i从working
memory写回到main memory中，新的i的值才能被其他线程所读取。从某个意义上说，可见性保证了各个线程的working
memory的数据的一致性。<br />
可见性遵循下面一些规则：</p>
<ul>
    <li>当一个线程运行结束的时候，所有写的变量都会被flush回main memory中。</li>
    <li>当一个线程第一次读取某个变量的时候，会从main memory中读取最新的。</li>
    <li>volatile的变量会被立刻写到main memory中的，在jsr133中，对volatile的语义进行增强，后面会提到</li>
    <li>当一个线程释放锁后，所有的变量的变化都会flush到main memory中，然后一个使用了这个相同的同步锁的进程，将会重新加载所有的使用到的变量，这样就保证了可见性。</li>
</ul>
<span id="_1">
<h4>原子性</h4>
</span>
<p>还拿上面的例子来说，原子性就是当某一个线程修改i的值的时候，从取出i到将新的i的值写给i之间不能有其他线程对i进行任何操作。也就是说保证某个线程对i的操作是原子性的，这样就可以避免数据脏读。<br />
通过锁机制或者CAS（Compare And Set 需要硬件CPU的支持）操作可以保证操作的原子性。</p>
<span id="_2">
<h4>有序性</h4>
</span>
<p>假设在main memory中存在两个变量i和j，初始值都为0，在某个线程A的代码中依次对i和j进行自增操作（i，j的操作不相互依赖），</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            </div>
            </td>
            <td>
            <div codecolorer="">i++;<br />
            j++;</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>由于，所以i,j修改操作的顺序可能会被重新排序。那么修改后的ij写到main memory中的时候，顺序可能就不是按照i，j的顺序了，这就是所谓的<a href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/jsr-133-faq.html#reordering">reordering</a>，
在单线程的情况下，当线程A运行结束的后i，j的值都加1了，在线程自己看来就好像是线程按照代码的顺序进行了运行（这些操作都是基于as-if-
serial语义的），即使在实际运行过程中，i，j的自增可能被重新排序了，当然计算机也不能帮你乱排序，存在上下逻辑关联的运行顺序肯定还是不会变
的。但是在多线程环境下，问题就不一样了，比如另一个线程B的代码如下</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            </div>
            </td>
            <td>
            <div codecolorer="">if(j==1) {<br />
            &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">System</a>.out.println(i);<br />
            }</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>按照我们的思维方式，当j为1的时候那么i肯定也是1，因为代码中i在j之前就自增了，但实际的情况有可能当j为1的时候i还是为0。这就是
reordering产生的不好的后果，所以我们在某些时候为了避免这样的问题需要一些必要的策略，以保证多个线程一起工作的时候也存在一定的次序。
JMM提供了happens-before 的排序策略。这样我们可以得到多线程环境下的as-if-serial语义。<br />
这里不对happens-before进行详细解释了,详细的请看这里<a href="http://www.ibm.com/developerworks/cn/java/j-jtp03304/">http://www.ibm.com/developerworks/cn/java/j-jtp03304/</a>，这里主要讲一下volatile在新的java内存模型下的变化，在jsr133之前，下面的代码可能会出现问题</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            4<br />
            5<br />
            6<br />
            7<br />
            8<br />
            9<br />
            10<br />
            11<br />
            12<br />
            </div>
            </td>
            <td>
            <div codecolorer=""><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Amap+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Map</a> configOptions;<br />
            char[] configText;<br />
            volatile boolean initialized = false;<br />
            // In Thread A<br />
            configOptions = new <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ahashmap+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">HashMap</a>();<br />
            configText = readConfigFile(fileName);<br />
            processConfigOptions(configText, configOptions);<br />
            initialized = true;<br />
            // In Thread B<br />
            while (!initialized) <br />
            &nbsp; sleep();<br />
            // use configOptions</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>jsr133之前，虽然对 volatile 变量的读和写不能与对其他 volatile 变量的读和写一起重新排序，但是它们仍然可以与对
nonvolatile 变量的读写一起重新排序，所以上面的Thread
A的操作，就可能initialized变成true的时候，而configOptions还没有被初始化，所以initialized先于
configOptions被线程B看到，就产生问题了。</p>
<blockquote>
<p><strong>JSR 133 Expert Group 决定让 volatile
读写不能与其他内存操作一起重新排序，新的内存模型下，如果当线程 A 写入 volatile 变量 V 而线程 B 读取 V 时，那么在写入 V
时，A 可见的所有变量值现在都可以保证对 B 是可见的。</strong></p>
</blockquote>
<p>结果就是作用更大的 volatile 语义，代价是访问 volatile 字段时会对性能产生更大的影响。这一点在ConcurrentHashMap中的统计某个segment元素个数的count变量中使用到了。</p>
<span id="HashMap">
<h2>二.线程安全的HashMap</h2>
</span>
<p>什么时候我们需要使用线程安全的hashmap呢，比如一个hashmap在运行的时候只有读操作，那么很明显不会有问题，但是当涉及到同时有改变
也有读的时候，就要考虑线程安全问题了，在不考虑性能问题的时候，我们的解决方案有Hashtable或者
Collections.synchronizedMap(hashMap)，这两种方式基本都是对整个hash表结构做锁定操作的，这样在锁表的期间，
别的线程就需要等待了，无疑性能不高。</p>
<span id="ConcurrentHashMap">
<h2>三.ConcurrentHashMap实现原理</h2>
</span>
<span id="_3">
<h4>数据结构</h4>
</span>
<p>ConcurrentHashMap的目标是实现支持高并发、高吞吐量的线程安全的HashMap。当然不能直接对整个hashtable加锁，所以在ConcurrentHashMap中，数据的组织结构和HashMap有所区别。<br />
<img src="http://geeklu.com/wp-content/uploads/2010/07/segments.png" alt="" title="segments" class="alignnone size-full wp-image-30887" width="436" height="288" /><br />
一个ConcurrentHashMap由多个segment组成，每一个segment都包含了一个HashEntry数组的hashtable，<br />
每一个segment包含了对自己的hashtable的操作，比如get，put，replace等操作，这些操作发生的时候，对自己的
hashtable进行锁定。由于每一个segment写操作只锁定自己的hashtable，所以可能存在多个线程同时写的情况，性能无疑好于只有一个
hashtable锁定的情况。<br />
<img src="http://geeklu.com/wp-content/uploads/2010/07/segment1.png" alt="" title="segment1" class="alignnone size-full wp-image-30889" width="321" height="205" /></p>
<span id="_4">
<h4>源码分析</h4>
</span>
<p>在ConcurrentHashMap的remove，put操作还是比较简单的，都是将remove或者put操作交给key所对应的segment去做的，所以当几个操作不在同一个segment的时候就可以并发的进行。</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            4<br />
            </div>
            </td>
            <td>
            <div codecolorer="">&nbsp; &nbsp; public V remove(<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Object</a> key) {<br />
            &nbsp; &nbsp; int hash = hash(key.hashCode());<br />
            &nbsp; &nbsp; &nbsp; &nbsp; return segmentFor(hash).remove(key, hash, null);<br />
            &nbsp; &nbsp; }</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>而segment中的remove操作除了加锁之外和HashMap中的remove操作基本无异。</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap; height: 500px;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            4<br />
            5<br />
            6<br />
            7<br />
            8<br />
            9<br />
            10<br />
            11<br />
            12<br />
            13<br />
            14<br />
            15<br />
            16<br />
            17<br />
            18<br />
            19<br />
            20<br />
            21<br />
            22<br />
            23<br />
            24<br />
            25<br />
            26<br />
            27<br />
            28<br />
            29<br />
            30<br />
            31<br />
            32<br />
            33<br />
            34<br />
            35<br />
            36<br />
            </div>
            </td>
            <td>
            <div codecolorer="">&nbsp; &nbsp; &nbsp; &nbsp; <span>/**<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Remove; match on key only if value null, else match both.<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
            &nbsp; &nbsp; &nbsp; &nbsp; V remove(<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Object</a> key, int hash, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Object</a> value) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lock();<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int c = count - 1;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashEntry&lt;K,V&gt;[] tab = table;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int index = hash &amp; (tab.length - 1);<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashEntry&lt;K,V&gt; first = tab[index];<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashEntry&lt;K,V&gt; e = first;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (e != null &amp;&amp; (e.hash != hash || !key.equals(e.key)))<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e = e.next;<br />
            <br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; V oldValue = null;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e != null) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; V v = e.value;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (value == null || value.equals(v)) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oldValue = v;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // All entries following removed node can stay<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // in list, but all preceding ones need to be<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // cloned.<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ++modCount;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashEntry&lt;K,V&gt; newFirst = e.next;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (HashEntry&lt;K,V&gt; p = first; p != e; p = p.next)<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newFirst = new HashEntry&lt;K,V&gt;(p.key, p.hash,<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newFirst, p.value);<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tab[index] = newFirst;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count = c; // write-volatile<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return oldValue;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } finally {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unlock();<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; }</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>上面的代码中关于volatile类型的变量count值得一提，这里充分利用了Java 5中对volatile语义的增强，count = c的操作必须在modCount，table等操作的后面，这样才能保证这些变量操作的可见性。<br />
Segment类继承于ReentrantLock，主要是为了使用ReentrantLock的锁，ReentrantLock的实现比<br />
synchronized在多个线程争用下的总体开销小。<br />
put操作和remove操作类似。</p>
<p>接下来我们来看下get操作。</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            4<br />
            </div>
            </td>
            <td>
            <div codecolorer="">&nbsp; &nbsp; public V get(<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Object</a> key) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; int hash = hash(key.hashCode());<br />
            &nbsp; &nbsp; &nbsp; &nbsp; return segmentFor(hash).get(key, hash);<br />
            &nbsp; &nbsp; }</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>也是使用了对应的segment的get</p>
<div java="" dawn="" style="overflow: auto; white-space: nowrap;">
<table cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td>
            <div>1<br />
            2<br />
            3<br />
            4<br />
            5<br />
            6<br />
            7<br />
            8<br />
            9<br />
            10<br />
            11<br />
            12<br />
            13<br />
            14<br />
            15<br />
            </div>
            </td>
            <td>
            <div codecolorer="">&nbsp; &nbsp; &nbsp; &nbsp;V get(<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky">Object</a> key, int hash) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (count != 0) { // read-volatile<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HashEntry&lt;K,V&gt; e = getFirst(hash);<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (e != null) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (e.hash == hash &amp;&amp; key.equals(e.key)) {<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; V v = e.value;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (v != null)<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return v;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return readValueUnderLock(e); // recheck<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e = e.next;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
            &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;<br />
            &nbsp; &nbsp; &nbsp; &nbsp; }</div>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>上面的代码中，一开始就对volatile变量count进行了读取比较，这个还是java5对volatile语义增强的作用，这样就可以获取变
量的可见性。所以count !=
0之后，我们可以认为对应的hashtable是最新的，当然由于读取的时候没有加锁，在get的过程中，可能会有更新。当发现根据key去找元素的时
候，但发现找得的key对应的value为null，这个时候可能会有其他线程正在对这个元素进行写操作，所以需要在使用锁的情况下在读取一下
value，以确保最终的值。</p>
<p>其他相关涉及读取的操作也都类似。</p>

<img src ="http://www.blogjava.net/jelver/aggbug/339963.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2010-12-07 10:50 <a href="http://www.blogjava.net/jelver/articles/339963.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>http请求的详细过程 【推荐】</title><link>http://www.blogjava.net/jelver/articles/304400.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 01 Dec 2009 08:47:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/304400.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/304400.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/304400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/304400.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/304400.html</trackback:ping><description><![CDATA[<p>对于一个做程序开发的人员来说基础知识非常重要，而在工作中常常忽略掉这些基本功的熟练掌握，无意看到这篇文章，觉得不错，特来转载，由于原创地址不明，在此不作标注，希望作者能理解。<br />
<a href="http://www.yuanma.org/data/2009/1009/article_3949.htm">http://www.yuanma.org/data/2009/1009/article_3949.htm</a></p>
<p><strong>一个http请求的详细过程</strong></p>
<p>我们来看当我们在浏览器输入<a href="http://www.mycompany.com:8080/mydir/index.html" rel="no-follow">http://www.mycompany.com:8080/mydir/index.html</a>,幕后所发生的一切。</p>
<p>首先http是一个应用层的协议，在这个层的协议，只是一种通讯规范，也就是因为双方要进行通讯，大家要事先约定一个规范。</p>
<p>1.连接 当我们输入这样一个请求时，首先要建立一个socket连接，因为socket是通过ip和端口建立的，所以之前还有一个DNS解析过程，把<a href="http://www.mycompany.com/" rel="no-follow">www.mycompany.com</a>变成ip，如果url里不包含端口号，则会使用该协议的默认端口号。</p>
<p>DNS的过程是这样的：首先我们知道我们本地的机器上在配置网络时都会填写DNS，这样本机就会把这个url发给这个配置的DNS服务器，如果能够找到相应的url则返回其ip，否则该DNS将继续将该解析请求发送给上级DNS，整个DNS可以看做是一个树状结构，该请求将一直发送到根直到得到结果。现在已经拥有了目标ip和端口号，这样我们就可以打开socket连接了。</p>
<p>2.请求 连接成功建立后，开始向web服务器发送请求，这个请求一般是GET或POST命令（POST用于FORM参数的传递）。GET命令的格式为：　　GET 路径/文件名 HTTP/1.0<br />
文件名指出所访问的文件，HTTP/1.0指出Web浏览器使用的HTTP版本。现在可以发送GET命令：</p>
<p>GET /mydir/index.html HTTP/1.0，</p>
<p>3.应答 web服务器收到这个请求，进行处理。从它的文档空间中搜索子目录mydir的文件index.html。如果找到该文件，Web服务器把该文件内容传送给相应的Web浏览器。</p>
<p>为了告知浏览器，，Web服务器首先传送一些HTTP头信息，然后传送具体内容（即HTTP体信息），HTTP头信息和HTTP体信息之间用一个空行分开。<br />
常用的HTTP头信息有：<br />
　　① HTTP 1.0 200 OK 　这是Web服务器应答的第一行，列出服务器正在运行的HTTP版本号和应答代码。代码"200 OK"表示请求完成。<br />
　　② MIME_Version:1.0　它指示MIME类型的版本。<br />
　　③ content_type:类型　这个头信息非常重要，它指示HTTP体信息的MIME类型。如：content_type:text/html指示传送的数据是HTML文档。<br />
　　④ content_length:长度值　它指示HTTP体信息的长度（字节）。</p>
<p><br />
4.关闭连接：当应答结束后，Web浏览器与Web服务器必须断开，以保证其它Web浏览器能够与Web服务器建立连接。</p>
<p><br />
<strong>下面我们具体分析其中的数据包在网络中漫游的经历</strong></p>
<p>在网络分层结构中，各层之间是严格单向依赖的。&#8220;服务&#8221;是描述各层之间关系的抽象概念，即网络中各层向紧邻上层提供的一组操作。下层是服务提供者，上层是请求服务的用户。服务的表现形式是原语（primitive），如系统调用或库函数。系统调用是操作系统内核向网络应用程序或高层协议提供的服务原语。网络中的n层总要向n+1层提供比n-1层更完备的服务，否则n层就没有存在的价值。 </p>
<p>传输层实现的是&#8220;端到端&#8221;通信，引进网间进程通信概念，同时也要解决差错控制，流量控制，数据排序（报文排序），连接管理等问题，为此提供不同的服务方式。通常传输层的服务通过系统调用的方式提供，以socket的方式。对于客户端，要想建立一个socket连接，需要调用这样一些函数socket() bind() connect(),然后就可以通过send()进行数据发送。</p>
<p><strong>现在看数据包在网络中的穿行过程：</strong></p>
<p>应用层</p>
<p>首先我们可以看到在应用层，根据当前的需求和动作，结合应用层的协议，有我们确定发送的数据内容，我们把这些数据放到一个缓冲区内，然后形成了应用层的报文<strong>data</strong>。</p>
<p>传输层</p>
<p>这些数据通过传输层发送，比如tcp协议。所以它们会被送到传输层处理，在这里报文打上了传输头的包头，主要包含端口号，以及tcp的各种制信息，这些信息是直接得到的，因为接口中需要指定端口。这样就组成了tcp的数据传送单位<strong>segment</strong>。tcp是一种端到端的协议，利用这些信息，比如tcp首部中的序号确认序号，根据这些数字，发送的一方不断的进行发送等待确认，发送一个数据段后，会开启一个计数器，只有当收到确认后才会发送下一个，如果超过计数时间仍未收到确认则进行重发，在接受端如果收到错误数据，则将其丢弃，这将导致发送端超时重发。通过tcp协议，控制了数据包的发送序列的产生，不断的调整发送序列，实现流控和数据完整。</p>
<p>网络层</p>
<p>然后待发送的数据段送到网络层，在网络层被打包，这样封装上了网络层的包头，包头内部含有源及目的的ip地址，该层数据发送单位被称为<strong>packet</strong>。网络层开始负责将这样的数据包在网络上传输，如何穿过路由器，最终到达目的地址。在这里，根据目的ip地址，就需要查找下一跳路由的地址。首先在本机，要查找本机的路由表，在windows上运行route print就可以看到当前路由表内容，有如下几项：<br />
Active Routes Default Route Persistent Route.</p>
<p>整个查找过程是这样的:<br />
(1)根据目的地址，得到目的网络号，如果处在同一个内网，则可以直接发送。<br />
(2)如果不是，则查询路由表，找到一个路由。<br />
(3)如果找不到明确的路由，此时在路由表中还会有默认网关，也可称为缺省网关，IP用缺省的网关地址将一个数据传送给下一个指定的路由器，所以网关也可能是路由器，也可能只是内网向特定路由器传输数据的网关。<br />
(4)路由器收到数据后，它再次为远程主机或网络查询路由，若还未找到路由，该数据包将发送到该路由器的缺省网关地址。而数据包中包含一个最大路由跳数，如果超过这个跳数，就会丢弃数据包，这样可以防止无限传递。路由器收到数据包后，只会查看网络层的包裹数据，目的ip。所以说它是工作在网络层，传输层的数据对它来说则是透明的。</p>
<p>如果上面这些步骤都没有成功，那么该数据报就不能被传送。如果不能传送的数据报来自本机，那么一般会向生成数据报的应用程序返回一个&#8220;主机不可达&#8221;或 &#8220;网络不可达&#8221;的错误。</p>
<p>&nbsp;</p>
<p>以windows下主机的路由表为例，看路由的查找过程<br />
======================================================================<br />
Active Routes:<br />
Network Destination&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Netmask&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gateway&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Interface&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Metric<br />
0.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10<br />
127.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;255.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br />
192.168.1.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 255.255.255.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10<br />
192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;255.255.255.255&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 127.0.0.1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;10<br />
192.168.1.255&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;255.255.255.255&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10<br />
&nbsp;224.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;240.0.0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10<br />
255.255.255.255&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;255.255.255.255&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br />
Default Gateway:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.2</p>
<p>Network Destination 目的网段&nbsp; <br />
Netmask 子网掩码&nbsp; <br />
Gateway 下一跳路由器入口的ip，路由器通过interface和gateway定义一调到下一个路由器的链路，通常情况下，interface和gateway是同一网段的。<br />
Interface 到达该目的地的本路由器的出口ip（对于我们的个人pc来说，通常由机算机A的网卡，用该网卡的IP地址标识，当然一个pc也可以有多个网卡）。</p>
<p>网关这个概念，主要用于不同子网间的交互，当两个子网内主机A,B要进行通讯时，首先A要将数据发送到它的本地网关，然后网关再将数据发送给B所在的网关，然后网关再发送给B。<br />
默认网关，当一个数据包的目的网段不在你的路由记录中，那么，你的路由器该把那个数据包发送到哪里！缺省路由的网关是由你的连接上的default gateway决定的，也就是我们通常在网络连接里配置的那个值。</p>
<p>通常interface和gateway处在一个子网内，对于路由器来说，因为可能具有不同的interface,当数据包到达时，根据Network Destination寻找匹配的条目，如果找到，interface则指明了应当从该路由器的那个接口出去，gateway则代表了那个子网的网关地址。</p>
<p>第一条&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0.0.0&nbsp;&nbsp; 0.0.0.0&nbsp;&nbsp; 192.168.1.2&nbsp;&nbsp;&nbsp; 192.168.1.101&nbsp;&nbsp; 10<br />
0.0.0.0代表了缺省路由。该路由记录的意思是：当我接收到一个数据包的目的网段不在我的路由记录中，我会将该数据包通过192.168.1.101这个接口发送到192.168.1.2这个地址，这个地址是下一个路由器的一个接口，这样这个数据包就可以交付给下一个路由器处理，与我无关。该路由记录的线路质量 10。当有多个条目匹配时，会选择具有较小Metric值的那个。</p>
<p>第三条&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 192.168.1.0&nbsp;&nbsp; 255.255.255.0&nbsp; 192.168.1.101&nbsp;&nbsp; 192.168.1.101&nbsp; 10<br />
直联网段的路由记录：当路由器收到发往直联网段的数据包时该如何处理，这种情况，路由记录的interface和gateway是同一个。当我接收到一个数据包的目的网段是192.168.1.0时，我会将该数据包通过192.168.1.101这个接口直接发送出去，因为这个端口直接连接着192.168.1.0这个网段，该路由记录的线路质量 10&nbsp;（因interface和gateway是同一个，表示数据包直接传送给目的地址，不需要再转给路由器）。</p>
<p>一般就分这两种情况，目的地址与当前路由器接口是否在同一子网。如果是则直接发送，不需再转给路由器，否则还需要转发给下一个路由器继续进行处理。</p>
<p>&nbsp;</p>
<p>查找到下一跳ip地址后，还需要知道它的mac地址，这个地址要作为链路层数据装进链路层头部。这时需要arp协议，具体过程是这样的，查找arp缓冲，windows下运行arp -a可以查看当前arp缓冲内容。如果里面含有对应ip的mac地址，则直接返回。否则需要发生arp请求，该请求包含源的ip和mac地址，还有目的地的ip地址，在网内进行广播，所有的主机会检查自己的ip与该请求中的目的ip是否一样，如果刚好对应则返回自己的mac地址，同时将请求者的ip mac保存。这样就得到了目标ip的mac地址。</p>
<p>链路层</p>
<p>将mac地址及链路层控制信息加到数据包里，形成<strong>Frame</strong>，Frame在链路层协议下，完成了相邻的节点间的数据传输，完成连接建立，控制传输速度，数据完整。</p>
<p>物理层</p>
<p>物理线路则只负责该数据以<strong>bit</strong>为单位从主机传输到下一个目的地。</p>
<p>下一个目的地接受到数据后，从物理层得到数据然后经过逐层的解包 到 链路层 到 网络层，然后开始上述的处理，在经网络层 链路层 物理层将数据封装好继续传往下一个地址。</p>
<p>在上面的过程中，可以看到有一个路由表查询过程，而这个路由表的建立则依赖于路由算法。也就是说路由算法实际上只是用来路由器之间更新维护路由表，真正的数据传输过程并不执行这个算法，只查看路由表。这个概念也很重要，需要理解常用的路由算法。而整个tcp协议比较复杂，跟链路层的协议有些相似，其中有很重要的一些机制或者概念需要认真理解，比如编号与确认，流量控制，重发机制，发送接受窗口。</p>
<p>&nbsp;</p>
<p><strong>tcp/ip基本模型及概念</strong></p>
<p><br />
<strong>物理层</strong></p>
<p>设备，中继器（repeater）,集线器（hub）。对于这一层来说，从一个端口收到数据，会转发到所有端口。</p>
<p><br />
<strong>链路层</strong></p>
<p>协议：SDLC（Synchronous Data Link Control）HDLC（High-level Data Link Control） ppp协议独立的链路设备中最常见的当属网卡，网桥也是链路产品。集线器MODEM的某些功能有人认为属于链路层，对此还有些争议认为属于物理层设备。除此之外，所有的交换机都需要工作在数据链路层，但仅工作在数据链路层的仅是二层交换机。其他像三层交换机、四层交换机和七层交换机虽然可对应工作在OSI的三层、四层和七层，但二层功能仍是它们基本的功能。</p>
<p>因为有了MAC地址表，所以才充分避免了冲突，因为交换机通过目的MAC地址知道应该把这个数据转发到哪个端口。而不会像HUB一样，会转发到所有滴端口。所以，交换机是可以划分冲突域滴。</p>
<p><br />
<strong>网络层</strong></p>
<p>四个主要的协议:&nbsp;&nbsp; <br />
网际协议IP：负责在主机和网络之间寻址和路由数据包。&nbsp;&nbsp;&nbsp;&nbsp; <br />
地址解析协议ARP：获得同一物理网络中的硬件主机地址。&nbsp;&nbsp;&nbsp;&nbsp; <br />
网际控制消息协议ICMP：发送消息，并报告有关数据包的传送错误。&nbsp;&nbsp;&nbsp;&nbsp; <br />
互联组管理协议IGMP：被IP主机拿来向本地多路广播路由器报告主机组成员。</p>
<p>该层设备有三层交换机，路由器。</p>
<p><br />
<strong>传输层</strong></p>
<p>两个重要协议 TCP 和 UDP 。</p>
<p>端口概念：TCP/UDP 使用 IP 地址标识网上主机，使用端口号来标识应用进程，即 TCP/UDP 用主机 IP 地址和为应用进程分配的端口号来标识应用进程。端口号是 16 位的无符号整数， TCP 的端口号和 UDP 的端口号是两个独立的序列。尽管相互独立，如果 TCP 和 UDP 同时提供某种知名服务，两个协议通常选择相同的端口号。这纯粹是为了使用方便，而不是协议本身的要求。利用端口号，一台主机上多个进程可以同时使用 TCP/UDP 提供的传输服务，并且这种通信是端到端的，它的数据由 IP 传递，但与 IP 数据报的传递路径无关。网络通信中用一个三元组可以在全局唯一标志一个应用进程：（协议，本地地址，本地端口号）。</p>
<p>也就是说tcp和udp可以使用相同的端口。</p>
<p>可以看到通过(协议,源端口，源ip，目的端口，目的ip)就可以用来完全标识一组网络连接。</p>
<p><strong>应用层</strong></p>
<p>基于tcp：Telnet FTP SMTP DNS HTTP <br />
基于udp：RIP NTP（网落时间协议）和DNS （DNS也使用TCP）SNMP TFTP</p>
<p>&nbsp;</p>
<p>参考文献：</p>
<p>读懂本机路由表 <a href="http://hi.baidu.com/thusness/blog/item/9c18e5bf33725f0818d81f52.html" rel="no-follow">http://hi.baidu.com/thusness/blog/item/9c18e5bf33725f0818d81f52.html</a></p>
<p>Internet 传输层协议 <a href="http://www.cic.tsinghua.edu.cn/jdx/book6/3.htm" rel="no-follow">http://www.cic.tsinghua.edu.cn/jdx/book6/3.htm</a></p>
<p>计算机网络 谢希仁</p>
<p><br />
&nbsp;</p>
<img src ="http://www.blogjava.net/jelver/aggbug/304400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2009-12-01 16:47 <a href="http://www.blogjava.net/jelver/articles/304400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>既有鱼肉又有熊掌——ListOrderedMap</title><link>http://www.blogjava.net/jelver/articles/291988.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 20 Aug 2009 10:22:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/291988.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/291988.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/291988.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/291988.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/291988.html</trackback:ping><description><![CDATA[要有序可以用List，要便于查找可以用Map，那既要有序又便于查找呢？<br />
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最近我就遇到了这样一个问题，Java没有给我们提供现成的类，我们完全可以自己开发个类继承List和Map（Java原来就有不可以同时继承List和Map的Bug，因此特意去看了下这个Bug的状态——Closed，呵呵，应该是很老的版本才有的问题，用新版本的朋友不用担心会遇到这个问题），但是完全没必要白花那个力气，因为Apache的<strong>Commons Collections</strong>的Jar包里已经为我们提供了一个相当完备的类来满足我们这样的要求完全是绰绰有余。因此我们现在要做的仅仅是引入Jar包，然后使用这个现成的好东西——<strong>ListOrderedMap</strong>就可以啦。<br />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;让我们来看看代码：</p>
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751550.gif" align="top" /><span style="color: #000000">ListOrderedMap&nbsp;list&nbsp;</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">new</span> <span style="color: #000000">&nbsp;ListOrderedMap();<br />
<img id="Codehighlighter1_81_123_Open_Image" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751551.gif" align="top" /><img id="Codehighlighter1_81_123_Closed_Image" style="display: none" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751552.gif" align="top" /></span> <span style="color: #0000ff">for</span> <span style="color: #000000">(</span> <span style="color: #0000ff">int</span> <span style="color: #000000">&nbsp;i&nbsp;</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">0</span> <span style="color: #000000">;&nbsp;i&nbsp;</span> <span style="color: #000000">&lt;</span> <span style="color: #000000">&nbsp;objs.length;&nbsp;i</span> <span style="color: #000000">++</span> <span style="color: #000000">)&nbsp;</span> <span id="Codehighlighter1_81_123_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751553.gif" /></span> <span id="Codehighlighter1_81_123_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751554.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;list.put(objs[i].getId(),&nbsp;objs[i]);<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751555.gif" align="top" />}</span> </span>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化很简单吧，没有一点技术难度，往里边放数据和Map没一点区别，需要注意的是Map我们可以在初始化的时候加上类型，比如Map&lt;String, String&gt;，但是ListOrderedMap不可以，就这么点差别，要记得哦。但是这个差别也是ListOrderedMap让人最不满意的地方，因为这说明他是类型不安全的。<br />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接下来，看看我们都用到了ListOrderedMap的哪些方法：</p>
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751550.gif" align="top" /><span style="color: #0000ff">int</span> <span style="color: #000000">&nbsp;themeId&nbsp;</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;((Obj)&nbsp;list.getValue(</span> <span style="color: #000000">0</span> <span style="color: #000000">)).getThemeId();<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751550.gif" align="top" /></span> <span style="color: #0000ff">int</span> <span style="color: #000000">&nbsp;index&nbsp;</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;list.indexOf(key);<br />
<img id="Codehighlighter1_113_148_Open_Image" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751551.gif" align="top" /><img id="Codehighlighter1_113_148_Closed_Image" style="display: none" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751552.gif" align="top" /></span> <span style="color: #0000ff">if</span> <span style="color: #000000">&nbsp;(index&nbsp;</span> <span style="color: #000000">==</span> <span style="color: #000000">&nbsp;list.size()&nbsp;</span> <span style="color: #000000">-</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">1</span> <span style="color: #000000">)&nbsp;</span> <span id="Codehighlighter1_113_148_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751553.gif" /></span> <span id="Codehighlighter1_113_148_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751554.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;obj</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;(Obj)&nbsp;list.getValue(</span> <span style="color: #000000">0</span> <span style="color: #000000">);<br />
<img id="Codehighlighter1_172_215_Open_Image" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751551.gif" align="top" /><img id="Codehighlighter1_172_215_Closed_Image" style="display: none" alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751552.gif" align="top" />}</span> </span><span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">else</span> <span style="color: #000000">&nbsp;</span> <span style="color: #0000ff">if</span> <span style="color: #000000">&nbsp;(index&nbsp;</span> <span style="color: #000000">!=</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">-</span> <span style="color: #000000">1</span> <span style="color: #000000">)&nbsp;</span> <span id="Codehighlighter1_172_215_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751553.gif" /></span> <span id="Codehighlighter1_172_215_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751554.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;obj</span> <span style="color: #000000">=</span> <span style="color: #000000">&nbsp;(Obj)&nbsp;list.getValue(index&nbsp;</span> <span style="color: #000000">+</span> <span style="color: #000000">&nbsp;</span> <span style="color: #000000">1</span> <span style="color: #000000">);<br />
<img alt="" src="http://manualdocument.cn/uploads/allimg/081209/1751555.gif" align="top" />}</span> </span>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>getValue(int index)</strong>直接根据Index取得Value，当然也可以直接根据Index取得Key值，方法名可不是getKey(int index)，而是直接<strong>get(int index)</strong>就可以啦。接着我们想取到当前Key值后面一个Key值所对应的Value，首先用<strong>indexOf(Object key)</strong>取得Index，然后计算其后面的Index再根据此Index取值。如果想取得当前Key值后面一个Key值，则不必要先取Index，这么麻烦，ListOrderedMap里有直接的方法可以取得当前Key值的前一个Key值和后一Key值，分别是<strong>previousKey(Object key)</strong>方法和<strong>nextKey(Object key)</strong>方法，返回null值表示到头（或尾）了，或者没有找到和当前Key值匹配的Key值&nbsp;。个至于这边为什么要有If和Else if，原因很简单，和一般的索引一样，返回值是-1就表示没有找到。我们在这里做了一个循环，而且我的这个ListOrderedMap的数列是确保长度大于0的，所以我把index==list.size()-1的判断放在了前边，如果不能确定长度是否大于0，还是先判断返回值是否为-1为好。<br />
<br />
话说多了容易糊涂，不如来个实例实在：<br />
<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_1_62_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1_62_Open_Text.style.display='none'; Codehighlighter1_1_62_Closed_Image.style.display='inline'; Codehighlighter1_1_62_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_1_62_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1_62_Closed_Text.style.display='none'; Codehighlighter1_1_62_Open_Image.style.display='inline'; Codehighlighter1_1_62_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_1_62_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**&nbsp;*/</span><span id="Codehighlighter1_1_62_Open_Text"><span style="color: #008000">/**</span><span style="color: #008000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;根据用户账号查找其拥有的实时视频列表<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;account<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@return</span><span style="color: #008000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000"><br />
<img id="Codehighlighter1_107_488_Open_Image" onclick="this.style.display='none'; Codehighlighter1_107_488_Open_Text.style.display='none'; Codehighlighter1_107_488_Closed_Image.style.display='inline'; Codehighlighter1_107_488_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_107_488_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_107_488_Closed_Text.style.display='none'; Codehighlighter1_107_488_Open_Image.style.display='inline'; Codehighlighter1_107_488_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;List&nbsp;findVideoList(String&nbsp;account)&nbsp;</span><span id="Codehighlighter1_107_488_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_107_488_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;videolist&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList();&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;sqlsb&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;StringBuffer(</span><span style="color: #000000">""</span><span style="color: #000000">);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlsb.append(</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;select&nbsp;username,videourl,cratedate&nbsp;from&nbsp;video&nbsp;v&nbsp;where&nbsp;v.customer_account&nbsp;='</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlsb.append(account);<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlsb.append(</span><span style="color: #000000">"</span><span style="color: #000000">'&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img id="Codehighlighter1_345_413_Open_Image" onclick="this.style.display='none'; Codehighlighter1_345_413_Open_Text.style.display='none'; Codehighlighter1_345_413_Closed_Image.style.display='inline'; Codehighlighter1_345_413_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_345_413_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_345_413_Closed_Text.style.display='none'; Codehighlighter1_345_413_Open_Image.style.display='inline'; Codehighlighter1_345_413_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_345_413_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_345_413_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;videolist&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;jdbcTemplate.queryForList(sqlsb.toString());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img id="Codehighlighter1_445_465_Open_Image" onclick="this.style.display='none'; Codehighlighter1_445_465_Open_Text.style.display='none'; Codehighlighter1_445_465_Closed_Image.style.display='inline'; Codehighlighter1_445_465_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_445_465_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_445_465_Closed_Text.style.display='none'; Codehighlighter1_445_465_Open_Image.style.display='inline'; Codehighlighter1_445_465_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(DataAccessException&nbsp;e)&nbsp;</span><span id="Codehighlighter1_445_465_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_445_465_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;videolist;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">取list里面的每行纪录中的username，createdate</span><span style="color: #008000"><br />
<img id="Codehighlighter1_571_961_Open_Image" onclick="this.style.display='none'; Codehighlighter1_571_961_Open_Text.style.display='none'; Codehighlighter1_571_961_Closed_Image.style.display='inline'; Codehighlighter1_571_961_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_571_961_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_571_961_Closed_Text.style.display='none'; Codehighlighter1_571_961_Open_Image.style.display='inline'; Codehighlighter1_571_961_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;getVideoList(String&nbsp;account)</span><span id="Codehighlighter1_571_961_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_571_961_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;videoService.findVideoList(account);<br />
<img id="Codehighlighter1_676_958_Open_Image" onclick="this.style.display='none'; Codehighlighter1_676_958_Open_Text.style.display='none'; Codehighlighter1_676_958_Closed_Image.style.display='inline'; Codehighlighter1_676_958_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_676_958_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_676_958_Closed_Text.style.display='none'; Codehighlighter1_676_958_Open_Image.style.display='inline'; Codehighlighter1_676_958_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(list</span><span style="color: #000000">!=</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;list.size()</span><span style="color: #000000">&gt;</span><span style="color: #000000">0</span><span style="color: #000000">)</span><span id="Codehighlighter1_676_958_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_676_958_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_713_954_Open_Image" onclick="this.style.display='none'; Codehighlighter1_713_954_Open_Text.style.display='none'; Codehighlighter1_713_954_Closed_Image.style.display='inline'; Codehighlighter1_713_954_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_713_954_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_713_954_Closed_Text.style.display='none'; Codehighlighter1_713_954_Open_Image.style.display='inline'; Codehighlighter1_713_954_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(i</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;i</span><span style="color: #000000">&lt;</span><span style="color: #000000">list.size();i</span><span style="color: #000000">++</span><span style="color: #000000">)</span><span id="Codehighlighter1_713_954_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_713_954_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListOrderedMap&nbsp;ob&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(ListOrderedMap)list.get(i);<br />
<img id="Codehighlighter1_814_943_Open_Image" onclick="this.style.display='none'; Codehighlighter1_814_943_Open_Text.style.display='none'; Codehighlighter1_814_943_Closed_Image.style.display='inline'; Codehighlighter1_814_943_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_814_943_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_814_943_Closed_Text.style.display='none'; Codehighlighter1_814_943_Open_Image.style.display='inline'; Codehighlighter1_814_943_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(ob</span><span style="color: #000000">!=</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;ob.size()</span><span style="color: #000000">&gt;</span><span style="color: #000000">0</span><span style="color: #000000">)</span><span id="Codehighlighter1_814_943_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_814_943_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(ob.getValue(</span><span style="color: #000000">0</span><span style="color: #000000">)</span><span style="color: #000000">+</span><span style="color: #000000">ob.getValue(</span><span style="color: #000000">2</span><span style="color: #000000">));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<p><br />
&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本文只简单介绍了ListOrderedMap的几种比较实用的方法，其他方法使用方法可以参考Apache网站上的相关API：http://commons.apache.org/collections/api-release/index.html</p>
<img src ="http://www.blogjava.net/jelver/aggbug/291988.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2009-08-20 18:22 <a href="http://www.blogjava.net/jelver/articles/291988.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA异常详解</title><link>http://www.blogjava.net/jelver/articles/253510.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Fri, 06 Feb 2009 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/253510.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/253510.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/253510.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/253510.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/253510.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->对于一个非常熟悉&nbsp;C++&nbsp;异常处理模型的程序员来说，它几乎可以不经任何其它培训和学习，就可以完全接受和能够轻松地使用&nbsp;Java&nbsp;语言中的异常处理编程方法...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/253510.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/253510.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2009-02-06 11:05 <a href="http://www.blogjava.net/jelver/articles/253510.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javaIO总结</title><link>http://www.blogjava.net/jelver/articles/253401.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 05 Feb 2009 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/253401.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/253401.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/253401.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/253401.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/253401.html</trackback:ping><description><![CDATA[一． Input和Output <br />
1. stream代表的是任何有能力产出数据的数据源，或是任何有能力接收数据的接收源。在Java的IO中，所有的stream（包括Input和Out stream）都包括两种类型： <br />
1.1 以字节为导向的stream <br />
以字节为导向的stream，表示以字节为单位从stream中读取或往stream中写入信息。以字节为导向的stream包括下面几种类型： <br />
1) input　stream： <br />
1) ByteArrayInputStream：把内存中的一个缓冲区作为InputStream使用 <br />
2) StringBufferInputStream：把一个String对象作为InputStream <br />
3) FileInputStream：把一个文件作为InputStream，实现对文件的读取操作 <br />
4) PipedInputStream：实现了pipe的概念，主要在线程中使用 <br />
5) SequenceInputStream：把多个InputStream合并为一个InputStream <br />
2) Out　stream <br />
1) ByteArrayOutputStream：把信息存入内存中的一个缓冲区中 <br />
2) FileOutputStream：把信息存入文件中 <br />
3) PipedOutputStream：实现了pipe的概念，主要在线程中使用 <br />
4) SequenceOutputStream：把多个OutStream合并为一个OutStream <br />
1.2 以Unicode字符为导向的stream <br />
以Unicode字符为导向的stream，表示以Unicode字符为单位从stream中读取或往stream中写入信息。以Unicode字符为导向的stream包括下面几种类型： <br />
1) Input　Stream <br />
1) CharArrayReader：与ByteArrayInputStream对应 <br />
2) StringReader：与StringBufferInputStream对应 <br />
3) FileReader：与FileInputStream对应 <br />
4) PipedReader：与PipedInputStream对应 <br />
2) Out　Stream <br />
1) CharArrayWrite：与ByteArrayOutputStream对应 <br />
2) StringWrite：无与之对应的以字节为导向的stream <br />
3) FileWrite：与FileOutputStream对应 <br />
4) PipedWrite：与PipedOutputStream对应 <br />
<br />
以字符为导向的stream基本上对有与之相对应的以字节为导向的stream。两个对应类实现的功能相同，字是在操作时的导向不同。如
CharArrayReader：和ByteArrayInputStream的作用都是把内存中的一个缓冲区作为InputStream使用，所不同的
是前者每次从内存中读取一个字节的信息，而后者每次从内存中读取一个字符。 <br />
1.3 两种不现导向的stream之间的转换 <br />
InputStreamReader和OutputStreamReader：把一个以字节为导向的stream转换成一个以字符为导向的stream。 <br />
2. stream添加属性 <br />
2.1 &#8220;为stream添加属性&#8221;的作用 <br />
运用上面介绍的Java中操作IO的API，我们就可完成我们想完成的任何操作了。但通过FilterInputStream和FilterOutStream的子类，我们可以为stream添加属性。下面以一个例子来说明这种功能的作用。 <br />
如果我们要往一个文件中写入数据，我们可以这样操作： <br />
FileOutStream fs = new FileOutStream(&#8220;test.txt&#8221;); <br />
然后就可以通过产生的fs对象调用write()函数来往test.txt文件中写入数据了。但是，如果我们想实现&#8220;先把要写入文件的数据先缓存到内存
中，再把缓存中的数据写入文件中&#8221;的功能时，上面的API就没有一个能满足我们的需求了。但是通过FilterInputStream和
FilterOutStream的子类，为FileOutStream添加我们所需要的功能。 <br />
2.2 FilterInputStream的各种类型 <br />
2.2.1 用于封装以字节为导向的InputStream <br />
1) DataInputStream：从stream中读取基本类型（int、char等）数据。 <br />
2) BufferedInputStream：使用缓冲区 <br />
3) LineNumberInputStream：会记录input stream内的行数，然后可以调用getLineNumber()和setLineNumber(int) <br />
4) PushbackInputStream：很少用到，一般用于编译器开发 <br />
2.2.2 用于封装以字符为导向的InputStream <br />
1) 没有与DataInputStream对应的类。除非在要使用readLine()时改用BufferedReader，否则使用DataInputStream <br />
2) BufferedReader：与BufferedInputStream对应 <br />
3) LineNumberReader：与LineNumberInputStream对应 <br />
4) PushBackReader：与PushbackInputStream对应 <br />
2.3 FilterOutStream的各种类型 <br />
2.2.3 用于封装以字节为导向的OutputStream <br />
1) DataIOutStream：往stream中输出基本类型（int、char等）数据。 <br />
2) BufferedOutStream：使用缓冲区 <br />
3) PrintStream：产生格式化输出 <br />
2.2.4 用于封装以字符为导向的OutputStream <br />
1) BufferedWrite：与对应 <br />
2) PrintWrite：与对应 <br />
3. RandomAccessFile <br />
1) 可通过RandomAccessFile对象完成对文件的读写操作 <br />
2) 在产生一个对象时，可指明要打开的文件的性质：r，只读；w，只写；rw可读写 <br />
3) 可以直接跳到文件中指定的位置 <br />
4. I/O应用的一个例子 <br />
<br />
<dl><dt>Java code</dt><dd>
<pre>
<div><!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--><span style="color: #0000ff;">import</span><span style="color: #000000;"> java.io.</span><span style="color: #000000;">*</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">public</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> TestIO{<br />
</span><span style="color: #0000ff;">public</span><span style="color: #0000ff;">static</span><span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args)<br />
</span><span style="color: #0000ff;">throws</span><span style="color: #000000;"> IOException{<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">1.以行为单位从一个文件读取数据</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">BufferedReader in </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedReader(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> FileReader(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon""TestIO.java</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
String s, s2 </span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> String();<br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((s </span><span style="color: #000000;">=</span><span style="color: #000000;"> in.readLine()) </span><span style="color: #000000;">!=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
s2 </span><span style="color: #000000;">+=</span><span style="color: #000000;"> s </span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">"n</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
in.close();<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">1b. 接收键盘的输入</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">BufferedReader stdin </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedReader(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> InputStreamReader(System.in));<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Enter a line:</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
System.out.println(stdin.readLine());<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">2. 从一个String对象中读取数据</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">StringReader in2 </span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> StringReader(s2);<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> c;<br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((c </span><span style="color: #000000;">=</span><span style="color: #000000;"> in2.read()) </span><span style="color: #000000;">!=</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
System.out.println((</span><span style="color: #0000ff;">char</span><span style="color: #000000;">)c);<br />
in2.close();<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">3. 从内存取出格式化输入</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">try</span><span style="color: #000000;">{<br />
DataInputStream in3 </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> DataInputStream(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> ByteArrayInputStream(s2.getBytes()));<br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">)<br />
System.out.println((</span><span style="color: #0000ff;">char</span><span style="color: #000000;">)in3.readByte()); <br />
}<br />
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(EOFException e){<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">End of stream</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
}<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">4. 输出到文件</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">try</span><span style="color: #000000;">{<br />
BufferedReader in4 </span><span style="color: #000000;">=</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedReader(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> StringReader(s2));<br />
PrintWriter out1 </span><span style="color: #000000;">=</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> PrintWriter(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedWriter(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> FileWriter(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" TestIO.out</span><span style="color: #000000;">"</span><span style="color: #000000;">)));<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> lineCount </span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((s </span><span style="color: #000000;">=</span><span style="color: #000000;"> in4.readLine()) </span><span style="color: #000000;">!=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)<br />
out1.println(lineCount</span><span style="color: #000000;">++</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">：</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;"> s);<br />
out1.close();<br />
in4.close();<br />
}<br />
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(EOFException ex){<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">End of stream</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
}<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">5. 数据的存储和恢复</span><span style="color: #008000;"><br />
</span><span style="color: #0000ff;">try</span><span style="color: #000000;">{<br />
DataOutputStream out2 </span><span style="color: #000000;">=</span><span style="color: #000000;"> <br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> DataOutputStream(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedOutputStream(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> FileOutputStream(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" Data.txt</span><span style="color: #000000;">"</span><span style="color: #000000;">)));<br />
out2.writeDouble(</span><span style="color: #000000;">3.1415926</span><span style="color: #000000;">);<br />
out2.writeChars(</span><span style="color: #000000;">"</span><span style="color: #000000;">"nThas was pi:writeChars"n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
out2.writeBytes(</span><span style="color: #000000;">"</span><span style="color: #000000;">Thas was pi:writeByte"n</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
out2.close();<br />
DataInputStream in5 </span><span style="color: #000000;">=</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> DataInputStream(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedInputStream(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> FileInputStream(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" Data.txt</span><span style="color: #000000;">"</span><span style="color: #000000;">)));<br />
BufferedReader in5br </span><span style="color: #000000;">=</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> BufferedReader(<br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> InputStreamReader(in5));<br />
System.out.println(in5.readDouble());<br />
System.out.println(in5br.readLine());<br />
System.out.println(in5br.readLine());<br />
}<br />
<br />
</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(EOFException e){<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">End of stream</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
}<br />
<br />
</span><span style="color: #008000;">//</span><span style="color: #008000;">6. 通过RandomAccessFile操作文件</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">RandomAccessFile rf </span><span style="color: #000000;">=</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> RandomAccessFile(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" rtest.dat</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">rw</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">; i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">10</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
rf.writeDouble(i</span><span style="color: #000000;">*</span><span style="color: #000000;">1.414</span><span style="color: #000000;">);<br />
rf.close();<br />
<br />
rf </span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> RandomAccessFile(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" rtest.dat</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">r</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">; i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">10</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Value </span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;"> i </span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">：</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;"> rf.readDouble());<br />
rf.close();<br />
<br />
rf </span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> RandomAccessFile(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" rtest.dat</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">rw</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
rf.seek(</span><span style="color: #000000;">5</span><span style="color: #000000;">*</span><span style="color: #000000;">8</span><span style="color: #000000;">);<br />
rf.writeDouble(</span><span style="color: #000000;">47.0001</span><span style="color: #000000;">);<br />
rf.close();<br />
<br />
rf </span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;"> RandomAccessFile(</span><span style="color: #000000;">"</span><span style="color: #000000;">F:""nepalon"" rtest.dat</span><span style="color: #000000;">"</span><span style="color: #000000;">, </span><span style="color: #000000;">"</span><span style="color: #000000;">r</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;"> i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">; i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">10</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Value </span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;"> i </span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">：</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;"> rf.readDouble());<br />
rf.close();<br />
}<br />
}<br />
</span></div>
<br />
</pre>
</dd></dl> <br />
<br />
<br />
关于代码的解释（以区为单位）： <br />
1区中，当读取文件时，先把文件内容读到缓存中，当调用in.readLine()时，再从缓存中以字符的方式读取数据（以下简称&#8220;缓存字节读取方式&#8221;）。 <br />
1b区中，由于想以缓存字节读取方式从标准IO（键盘）中读取数据，所以要先把标准IO（System.in）转换成字符导向的stream，再进行BufferedReader封装。 <br />
2区中，要以字符的形式从一个String对象中读取数据，所以要产生一个StringReader类型的stream。 <br />
4区中，对String对象s2读取数据时，先把对象中的数据存入缓存中，再从缓冲中进行读取；对TestIO.out文件进行操作时，先把格式化后的信息输出到缓存中，再把缓存中的信息输出到文件中。 <br />
5区中，对Data.txt文件进行输出时，是先把基本类型的数据输出屋缓存中，再把缓存中的数据输出到文件中；对文件进行读取操作时，先把文件中的数据
读取到缓存中，再从缓存中以基本类型的形式进行读取。注意in5.readDouble()这一行。因为写入第一个writeDouble()，所以为了
正确显示。也要以基本类型的形式进行读取。 <br />
6区是通过RandomAccessFile类对文件进行操作。
<img src ="http://www.blogjava.net/jelver/aggbug/253401.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2009-02-05 14:52 <a href="http://www.blogjava.net/jelver/articles/253401.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>j2ee的性能调优 </title><link>http://www.blogjava.net/jelver/articles/223922.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Sat, 23 Aug 2008 16:33:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/223922.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/223922.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/223922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/223922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/223922.html</trackback:ping><description><![CDATA[<h2>来源：中国IT实验室<br />
<br />
摘要:我提倡使用最小化资源的方式做一次压力测试，排除大部分浅显的应用问题。最小资源的意思，即在pc环境，使用应用可以运行的最小资源状态下，进行压力测试和性能问题侦测的工作。<br />
<br />
前面看到有人讲j2ee的性能调优，虽然这块不是自己的专长，但是猪养多了，也忍不住跳出来说几句。<br />
<br />
虽然几乎每本讲性能调优的书籍开篇都会提，没必要的情况下就不要做调优，但是我个人还是认为，所有系统在上线前，都应该做一次基本的压力测试并对相关的
性能问题进行检测， 但是迫于资源压力，很多项目都无法做正规的压力测试，一直到系统上线出现问题，才倒回来找原因。
而正规的压力测试，往往因为需要严格模拟生产环境，需要耗费大量的资源，各类专家配合解决问题，并不是那么轻松的可以做下来的。<br />
<br />
而
j2ee应用的特点就是以复杂性来回避传统问题，所以任意一个j2ee的部署，相对于php那样的结构都是比较复杂的。系统一旦发生性能问题，必须在程
序、数据库、应用服务器、jvm、操作系统几大块中交叉进行考虑，根据实际情况问题，问题的原因可能异常复杂。我们可以想象一个项目，从来不做UT不做
IT ，只做一次UAT，然后直接提交给用户上线以后，修补错误的困难度和成本。<br />
<br />
经常看到一些调优的最后解决方案，可以肯定，几乎
80%以上都是一些低级的程序错误导致的，剩下的20%虽然可能是用硬件，os参数调整等等问题解决了，但是其中很大一块，归根到底也是程序的问题。
而在我们回顾这些错误的时候可以很惊人的发现，大部分都是一些低级错误。<br />
<br />
我提倡使用最小化资源的方式做一次压力测试，排除大部分浅显的应用问题。最小资源的意思，即在pc环境，使用应用可以运行的最小资源状态下，进行压力测试和性能问题侦测的工作。这种做法的优点如下。<br />
<br />
1. 环境容易搭建， 特别是不需要考虑大型硬件和网络条件等等，也回避了开发人员可能不熟悉unix和特定应用服务器等问题<br />
<br />
2. 不需要特别的数据库，操作系统和应用服务器专家配合，开发人员自身即可完成。<br />
<br />
3. 不需要特别的依赖os和应用服务器，jvm的监测工具。选择自己最熟悉的即可。<br />
<br />
4. 开发人员在熟悉这种过程以后，再转到正式的生产环境工作时也更有经验，更容易解决问题。<br />
<br />
对测试过程做一点简单介绍。<br />
<br />
工具准备：<br />
<br />
得益于开源技术的发展，大部分工具都可以免费获得，使用也比较简单。<br />
<br />
1. jvm 监控： 对jvm的运行状态进行分析， 可以使用jvm自身带的特性输出日志，结合hp的jmeter profile进行分析。也可以使用jrockit自带的图形化工具mession control。<br />
<br />
熟悉什么用什么，越简单越好，目的主要是观察内存堆的变化，线程资源变化，gc情况等。<br />
<br />
2. 数据库监控工具： 熟悉数据库的使用数据库自身的特性，不熟悉的可以使用第三方工具，主要目的是观察数据库的锁，连接数信息， 对于db2我比较喜欢使用quest central。 oracle使用OEM或者自身的数据字典已经可以。<br />
<br />
3. 应用服务器监控： 主要目的是记录方法的调用情况和执行时间
，找出频繁调用的方法和执行时间过长的方法。使用jprobe和jprofile都可以很轻松的做到。
如果使用的应用服务器比较偏门，那么可以换一个支持这种检测工具的应用服务器。反正主要目的只是在找问题。<br />
<br />
4.  sql执行监控：跟踪找出执行时间过长的sql。 我喜欢使用p6spy。<br />
<br />
5. 压力工具： jmeter+badboy , 有条件的可以用loadrunner， 和loadrunner近似的还有一个免费的开源产品。
另外web 应用的话， 也可以使用selenium这样的ff扩展来做。微软vs自带的也不错，反正是什么简单用什么。<br />
<br />
6. 记录表格： 对问题和资源配置的变更进行记录和对比。<br />
<br />
我发现有些人做压力测试，只用压力工具来跑，不肯用各类proile工具来跟踪应用和数据库使用情况，加上经验又不足，结果测来测去都是瞎猜。<br />
<br />
设置：<br />
<br />
1. 数据库： 如果未使用连接池， 则尽可能的将数据库允许连接设置成最小数字，推荐是从1开始。如果使用连接池，则设置为1.<br />
<br />
随着并发模拟数的增加也可以适当上调，但是一定要低于压力工具模拟的并发用户数。数据库环境尽可能接近生产环境，至少要有足够的测试数据。<br />
<br />
2. 应用服务器： 对jvm启动堆做最小化设置。比应用服务器要求的最低内存略高，保证应用可以正常启动即可。根据模拟用户数增加可以小步适当上调，但是以保证应用基本运行即可。千万别来大内存。<br />
<br />
3. 压力模拟并发数，从1开始逐步往上加。一次加1，2个，上限不要太高，5-10个足以。<br />
<br />
步骤<br />
<br />
1. 按1用户1连接的方式进行检测<br />
<br />
* 找出系统是否存在明显的资源泄露，比如数据库连接，如果存在泄露此种情况下服务器很容易就hold。<br />
<br />
* 找出执行时间过长的java方法和sql。进行分析修改。<br />
<br />
* 找出那些调用过多的方法和sql，对程序进行分析，看是否做了不必要的调用。 这个问题尤其在使用了第三方包的情况下要小心，我曾经监测出某人写的东西一个方法间接的调用了数据库操作近200次。<br />
<br />
有些人做测试喜欢从5以上的数字开始，实在不是什么好习惯，比较明显的问题都容易回避了。<br />
<br />
2. 适当增加并发用户，尽可能不调整应用内存，对系统进行长时间的压力测试，比如2-4个小时。 重点观察是否存在内存泄露问题。
内存泄露的问题比较复杂，有时候还依赖于jvm和os，另外有些内存泄露只能在大并发的多线程环境下才会出现。
但是这种测试可以排除掉一些明显的问题，主要是缓存和队列之类的东西。内存泄露一般jvm会有报错和相关的日志dump文件。<br />
<br />
3.  逐步增加并发用户和连接数，观察是否存在sql锁 和线程锁的问题。另外并发情况下也可能存在其他一些资源冲突，比如读写文件的情况等等。<br />
<br />
线程情况可以使用监控工具观察，比如jrockit带的mc， 也可以直接dump jvm 内存快照找工具分析。<br />
<br />
4.
尽可能增加并发用户数，以当前应用能承担的上线进行长时间测试，比如半天到1天，观察是否会存在内存泄露，是否会存在线程资源消耗的问题。也需要检查一下
数据库的连接数情况，看是否会一直持续增加，这说明连接池实现有问题，或者设置过大，也可能是jdbc的问题。<br />
<br />
5. 其他： 对jvm 可以使用sun和bea的都对比跑一下， 两个实现情况大不同。 jr大并发支持好，所以可能jr上没问题，但是sun的就有问题了。<br />
<br />
大部分的问题应该都可以在步骤1，2能得到暴露。在完成了这样的初步测试以后，正式的测试就省心不少了，如果客户有钱，性能不好也可以直接更新硬件了，省事又创造GDP。</h2>
<img src ="http://www.blogjava.net/jelver/aggbug/223922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-08-24 00:33 <a href="http://www.blogjava.net/jelver/articles/223922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用HttpURLConnection连接servlet，发送接收xml包(转)</title><link>http://www.blogjava.net/jelver/articles/221073.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Sat, 09 Aug 2008 14:41:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/221073.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/221073.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/221073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/221073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/221073.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: import&nbsp;java.io.*;import&nbsp;java.net.*;/**&nbsp;*//***&nbsp;Title:连接servlet，发送请求包，获得返回包&nbsp;*&nbsp;Description:&nbsp;*&nbsp;Copyright:&nbsp;Copyright&nbsp;(c)&nbsp;2005*&nbsp;Comp...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/221073.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/221073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-08-09 22:41 <a href="http://www.blogjava.net/jelver/articles/221073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HttpURLConnection常用处理方式</title><link>http://www.blogjava.net/jelver/articles/199472.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Fri, 09 May 2008 05:25:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/199472.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/199472.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/199472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/199472.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/199472.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: /**//*&nbsp;*&nbsp;Classname&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;GameSoapProcessor&nbsp;*&nbsp;Create&nbsp;Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;2008-5-7&nbsp;*/package&nbsp;cn....&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/199472.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/199472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-05-09 13:25 <a href="http://www.blogjava.net/jelver/articles/199472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java分页</title><link>http://www.blogjava.net/jelver/articles/198579.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Mon, 05 May 2008 14:18:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/198579.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/198579.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/198579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/198579.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/198579.html</trackback:ping><description><![CDATA[定义两个vector，一个为储存查询所有记录的totalv,另一个储存当前页的记录currentpagev; <br />
总的记录数：int totalsize = totalv.getsize(); <br />
每页显示的记录数：int countperpage; <br />
总页数：int totalpagenum = totalsize/countperpage; <br />
//如果总的记录数和每页记录数的余数大于零， <br />
//那么总的页数为他们的整除结果加一 <br />
if (totalsize%countperpage &gt; 0 ){ <br />
totalpagenum = totalsize/countperpage + 1; <br />
} <br />
当前的页数：pagenum； <br />
<br />
for (int j = 0;j&lt;totalv.size();j++){ <br />
//分页，根据当前的页数和每页显示的记录数从totalv中取出记录 <br />
//往currentpagev中添加记录； <br />
//如果当前记录在(当前页码-1)*每页显示记录数（包括等于） <br />
//和 当前页码*每页显示记录数（不包括等于）之间的时候； <br />
//就属于该页的数据 <br />
if ( (j &gt;= (pagenum - 1) * countperpage) &amp;&amp; (j &lt; pagenum * countperpage)) { <br />
currentpagev.addelement(totalv.get(j)); <br />
} <br />
//当currentpagev记录数等于每页显示记录数， <br />
//停止往currentpagev中添加记录 <br />
if (currentpagev.size() == countperpage) { <br />
break; <br />
} <br />
} <br />
那么，当前页中显示的记录，就是currentpagev中的记录。 
<img src ="http://www.blogjava.net/jelver/aggbug/198579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-05-05 22:18 <a href="http://www.blogjava.net/jelver/articles/198579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在java中理解“回调函数” </title><link>http://www.blogjava.net/jelver/articles/189086.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 27 Mar 2008 09:40:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/189086.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/189086.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/189086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/189086.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/189086.html</trackback:ping><description><![CDATA[<p><font face="Arial">所谓回调，就是客户程序C调用服务程序S中的某个函数A，然后S又在某个时候反过来调用C中的某个函数B，对于C来说，这个B便叫做回调函数。<br />
<br />
一般说来，C不会自己调用B，C提供B的目的就是让S来调用它，而且是C不得不提供。由于S并不知道C提供的B叫甚名谁，所以S会约定B的接口规范（函数原型），然后由C提前通过S的一个函数R告诉S自己将要使用B函数，这个过程称为回调函数的注册，R称为注册函数。<br />
<br />
下面举个通俗的例子：<br />
<br />
某天，我打电话向你请教问题，当然是个难题，:)，你一时想不出解决方法，我又不能拿着电话在那里傻等，于是我们约定：等你想出办法后打手机通知我，这样，我就挂掉电话办其它事情去了。过了XX分钟，我的手机响了，你兴高采烈的说问题已经搞定，应该如此这般处理。故事到此结束。<br />
<br />
这个例子说明了&#8220;异步+回调&#8221;的编程模式。其中，你后来打手机告诉我结果便是一个&#8220;回调&#8221;过程；我的手机号码必须在以前告诉你，这便是注册回调函数；我的手机号码应该有效并且手机能够接收到你的呼叫，这是回调函数必须符合接口规范。</font></p>
<br />
<p><font face="Arial">如果你还不太清楚看看这段描述合和代码：<br />
<br />
声明一个接口，另外一个类有方法里面有个参数以是这个接口类型的，而后在另外类中实现这个接口(java中多用的是匿名内部类)，而且以这个匿名的类生成的对象为参数传到上面提到类中，而后实现回调.......这种用法可以参考java里面常用到的数据库操作所用到的几个接口.....<br />
<br />
注：匿名内部类 的说明可以见 <a href="http://dev.csdn.net/author/CMTobby/339cbab3897f4106bed2fe2ecd75470a.html" target="_blank">http://dev.csdn.net/author/CMTobby/339cbab3897f4106bed2fe2ecd75470a.html</a></font></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #008000">//</span><span style="color: #008000">声明一个接口</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000"><br />
<img id="Codehighlighter1_40_63_Open_Image" onclick="this.style.display='none'; Codehighlighter1_40_63_Open_Text.style.display='none'; Codehighlighter1_40_63_Closed_Image.style.display='inline'; Codehighlighter1_40_63_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_40_63_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_40_63_Closed_Text.style.display='none'; Codehighlighter1_40_63_Open_Image.style.display='inline'; Codehighlighter1_40_63_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">&nbsp;ICallBack()</span><span id="Codehighlighter1_40_63_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_40_63_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;postExec();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">另外一个类有方法里面有个参数以是这个接口类型的</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000"><br />
<img id="Codehighlighter1_120_309_Open_Image" onclick="this.style.display='none'; Codehighlighter1_120_309_Open_Text.style.display='none'; Codehighlighter1_120_309_Closed_Image.style.display='inline'; Codehighlighter1_120_309_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_120_309_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_120_309_Closed_Text.style.display='none'; Codehighlighter1_120_309_Open_Image.style.display='inline'; Codehighlighter1_120_309_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;FooBar..</span><span id="Codehighlighter1_120_309_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_120_309_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;ICallBack&nbsp;callBack;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_199_233_Open_Image" onclick="this.style.display='none'; Codehighlighter1_199_233_Open_Text.style.display='none'; Codehighlighter1_199_233_Closed_Image.style.display='inline'; Codehighlighter1_199_233_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_199_233_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_199_233_Closed_Text.style.display='none'; Codehighlighter1_199_233_Open_Image.style.display='inline'; Codehighlighter1_199_233_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;setCallBack(ICallBack&nbsp;callBack)</span><span id="Codehighlighter1_199_233_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_199_233_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.callBack</span><span style="color: #000000">=</span><span style="color: #000000">callBack;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_257_300_Open_Image" onclick="this.style.display='none'; Codehighlighter1_257_300_Open_Text.style.display='none'; Codehighlighter1_257_300_Closed_Image.style.display='inline'; Codehighlighter1_257_300_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_257_300_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_257_300_Closed_Text.style.display='none'; Codehighlighter1_257_300_Open_Image.style.display='inline'; Codehighlighter1_257_300_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;doSth()</span><span id="Codehighlighter1_257_300_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_257_300_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" />.<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;callBack.postExec();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;..<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">---------------------------------------</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />回调的实现<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_377_583_Open_Image" onclick="this.style.display='none'; Codehighlighter1_377_583_Open_Text.style.display='none'; Codehighlighter1_377_583_Closed_Image.style.display='inline'; Codehighlighter1_377_583_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_377_583_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_377_583_Closed_Text.style.display='none'; Codehighlighter1_377_583_Open_Image.style.display='inline'; Codehighlighter1_377_583_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Test</span><span id="Codehighlighter1_377_583_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_377_583_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_421_580_Open_Image" onclick="this.style.display='none'; Codehighlighter1_421_580_Open_Text.style.display='none'; Codehighlighter1_421_580_Closed_Image.style.display='inline'; Codehighlighter1_421_580_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_421_580_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_421_580_Closed_Text.style.display='none'; Codehighlighter1_421_580_Open_Image.style.display='inline'; Codehighlighter1_421_580_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)</span><span id="Codehighlighter1_421_580_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_421_580_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FooBar&nbsp;foo</span><span style="color: #000000">=</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;FooBar();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_491_572_Open_Image" onclick="this.style.display='none'; Codehighlighter1_491_572_Open_Text.style.display='none'; Codehighlighter1_491_572_Closed_Image.style.display='inline'; Codehighlighter1_491_572_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_491_572_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_491_572_Closed_Text.style.display='none'; Codehighlighter1_491_572_Open_Image.style.display='inline'; Codehighlighter1_491_572_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo.setCallBack(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ICallBack()</span><span id="Codehighlighter1_491_572_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_491_572_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_524_564_Open_Image" onclick="this.style.display='none'; Codehighlighter1_524_564_Open_Text.style.display='none'; Codehighlighter1_524_564_Closed_Image.style.display='inline'; Codehighlighter1_524_564_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_524_564_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_524_564_Closed_Text.style.display='none'; Codehighlighter1_524_564_Open_Image.style.display='inline'; Codehighlighter1_524_564_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;postExec()</span><span id="Codehighlighter1_524_564_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_524_564_Open_Text"><span style="color: #000000">{System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">method&nbsp;executed.</span><span style="color: #000000">"</span><span style="color: #000000">);}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<img src ="http://www.blogjava.net/jelver/aggbug/189086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-27 17:40 <a href="http://www.blogjava.net/jelver/articles/189086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络编程中的异步编程</title><link>http://www.blogjava.net/jelver/articles/189060.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 27 Mar 2008 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/189060.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/189060.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/189060.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/189060.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/189060.html</trackback:ping><description><![CDATA[该文章对编写客户服务器应用的java程序员有所帮助,可以解决程序在对方出现故障的时候继续稳定运行.<br />
　　目前java平台已经广泛应用于各类客户/服务器系统中，在实际编程中，往往需要网络的异步处理。比如客户程序，如果客户程序运行先于服务程序，则客户程序则需要在服务程序启动后再自动连接服务程序；在客户程序运行中如果服务程序中途停止，则也需要在不停止的条件下，等待服务程序运行并重新连接。下面提供了一类异步编程的方法。<br />
网络异步应用涉及到如下几个关键点： <br />
　　客户应用启动后，检测服务应用是否存在。如果不存在，则等待服务应用启动，同时不堵塞客户应用其他任务的执行。一旦服务应用启动，客户应用应该及时的与其建立连接。 <br />
　　客户应用和服务应用在数据通信中，服务应用异常退出后，客户应用应可以检测到服务应用的退出。同时客户应用自动清除该通信链路，回到初始状态，等待服务应用重新启动。<br />
　　该网络异步编程首先涉及到一个定时器和定时器事件。该定时器用于不断的检测网络中客户应用和服务应用是否连通，同时在服务应用出现异常时中止数据通信，返回到初始状态。网络的故障可以通过网络方法的异常处理获知。<br />
　　定时器包含在网络通信类中，使得使用该类的应用感知不到定时器的存在，而方便的处理网络信息。<br />
该客户程序类如下结构： <br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_0_238_Open_Image" onclick="this.style.display='none'; Codehighlighter1_0_238_Open_Text.style.display='none'; Codehighlighter1_0_238_Closed_Image.style.display='inline'; Codehighlighter1_0_238_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_0_238_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_0_238_Closed_Text.style.display='none'; Codehighlighter1_0_238_Open_Image.style.display='inline'; Codehighlighter1_0_238_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span id="Codehighlighter1_0_238_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**/</span><span id="Codehighlighter1_0_238_Open_Text"><span style="color: #008000">/*</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;*&nbsp;Classname&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;NetComm.java<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;*&nbsp;Create&nbsp;Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;5:04:00&nbsp;PM<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;*&nbsp;Author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;Administrator<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;*&nbsp;Product&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;tagApp<br />
<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;jdom;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.awt.event.ActionEvent;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.awt.event.ActionListener;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.BufferedReader;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.BufferedWriter;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.IOException;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.InputStreamReader;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.OutputStream;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.OutputStreamWriter;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.net.InetAddress;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.net.Socket;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_618_1974_Open_Image" onclick="this.style.display='none'; Codehighlighter1_618_1974_Open_Text.style.display='none'; Codehighlighter1_618_1974_Closed_Image.style.display='inline'; Codehighlighter1_618_1974_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_618_1974_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_618_1974_Closed_Text.style.display='none'; Codehighlighter1_618_1974_Open_Image.style.display='inline'; Codehighlighter1_618_1974_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;NetComm&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;ActionListener&nbsp;</span><span id="Codehighlighter1_618_1974_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_618_1974_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;javax.swing.Timer&nbsp;timer&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;javax.swing.Timer(</span><span style="color: #000000">3000</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;sock;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;EventNotifier&nbsp;en;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;net_state&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;InetAddress&nbsp;ServerAddr;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;ServerPort;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_850_895_Open_Image" onclick="this.style.display='none'; Codehighlighter1_850_895_Open_Text.style.display='none'; Codehighlighter1_850_895_Closed_Image.style.display='inline'; Codehighlighter1_850_895_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_850_895_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_850_895_Closed_Text.style.display='none'; Codehighlighter1_850_895_Open_Image.style.display='inline'; Codehighlighter1_850_895_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;NetComm(InetAddress&nbsp;addr,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;port)&nbsp;</span><span id="Codehighlighter1_850_895_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_850_895_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerAddr&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;addr;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServerPort&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;port;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">初始化并创建socket连接</span><span style="color: #008000"><br />
<img id="Codehighlighter1_944_1086_Open_Image" onclick="this.style.display='none'; Codehighlighter1_944_1086_Open_Text.style.display='none'; Codehighlighter1_944_1086_Closed_Image.style.display='inline'; Codehighlighter1_944_1086_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_944_1086_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_944_1086_Closed_Text.style.display='none'; Codehighlighter1_944_1086_Open_Image.style.display='inline'; Codehighlighter1_944_1086_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;NetComm_Init()&nbsp;</span><span id="Codehighlighter1_944_1086_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_944_1086_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net_state&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_970_1020_Open_Image" onclick="this.style.display='none'; Codehighlighter1_970_1020_Open_Text.style.display='none'; Codehighlighter1_970_1020_Closed_Image.style.display='inline'; Codehighlighter1_970_1020_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_970_1020_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_970_1020_Closed_Text.style.display='none'; Codehighlighter1_970_1020_Open_Image.style.display='inline'; Codehighlighter1_970_1020_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_970_1020_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_970_1020_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sock&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Socket(ServerAddr,&nbsp;ServerPort);<br />
<img id="Codehighlighter1_1044_1066_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1044_1066_Open_Text.style.display='none'; Codehighlighter1_1044_1066_Closed_Image.style.display='inline'; Codehighlighter1_1044_1066_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1044_1066_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1044_1066_Closed_Text.style.display='none'; Codehighlighter1_1044_1066_Open_Image.style.display='inline'; Codehighlighter1_1044_1066_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(IOException&nbsp;e)&nbsp;</span><span id="Codehighlighter1_1044_1066_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1044_1066_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net_state&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer.start();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">创建socket连接</span><span style="color: #008000"><br />
<img id="Codehighlighter1_1135_1729_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1135_1729_Open_Text.style.display='none'; Codehighlighter1_1135_1729_Closed_Image.style.display='inline'; Codehighlighter1_1135_1729_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1135_1729_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1135_1729_Closed_Text.style.display='none'; Codehighlighter1_1135_1729_Open_Image.style.display='inline'; Codehighlighter1_1135_1729_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;NetComm_Data()&nbsp;</span><span id="Codehighlighter1_1135_1729_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1135_1729_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1144_1643_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1144_1643_Open_Text.style.display='none'; Codehighlighter1_1144_1643_Closed_Image.style.display='inline'; Codehighlighter1_1144_1643_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1144_1643_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1144_1643_Closed_Text.style.display='none'; Codehighlighter1_1144_1643_Open_Image.style.display='inline'; Codehighlighter1_1144_1643_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1144_1643_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1144_1643_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;outputstream&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sock.getOutputStream();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedWriter&nbsp;out&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;BufferedWriter(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;OutputStreamWriter(<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outputstream));<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(</span><span style="color: #000000">"</span><span style="color: #000000">java&nbsp;by&nbsp;ghf@china.com</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.flush();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader&nbsp;in&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;BufferedReader(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;InputStreamReader(sock<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getInputStream()));<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;more&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_1482_1623_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1482_1623_Open_Text.style.display='none'; Codehighlighter1_1482_1623_Closed_Image.style.display='inline'; Codehighlighter1_1482_1623_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1482_1623_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1482_1623_Closed_Text.style.display='none'; Codehighlighter1_1482_1623_Open_Image.style.display='inline'; Codehighlighter1_1482_1623_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(more)&nbsp;</span><span id="Codehighlighter1_1482_1623_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1482_1623_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;in.readLine();<br />
<img id="Codehighlighter1_1537_1562_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1537_1562_Open_Text.style.display='none'; Codehighlighter1_1537_1562_Closed_Image.style.display='inline'; Codehighlighter1_1537_1562_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1537_1562_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1537_1562_Closed_Text.style.display='none'; Codehighlighter1_1537_1562_Open_Image.style.display='inline'; Codehighlighter1_1537_1562_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(str&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1537_1562_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1537_1562_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;more&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_1569_1618_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1569_1618_Open_Text.style.display='none'; Codehighlighter1_1569_1618_Closed_Image.style.display='inline'; Codehighlighter1_1569_1618_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1569_1618_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1569_1618_Closed_Text.style.display='none'; Codehighlighter1_1569_1618_Open_Image.style.display='inline'; Codehighlighter1_1569_1618_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1569_1618_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1569_1618_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;处理数据</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.close();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1667_1709_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1667_1709_Open_Text.style.display='none'; Codehighlighter1_1667_1709_Closed_Image.style.display='inline'; Codehighlighter1_1667_1709_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1667_1709_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1667_1709_Closed_Text.style.display='none'; Codehighlighter1_1667_1709_Open_Image.style.display='inline'; Codehighlighter1_1667_1709_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(IOException&nbsp;e)&nbsp;</span><span id="Codehighlighter1_1667_1709_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1667_1709_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NetComm_Close();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;net_state&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer.start();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1761_1845_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1761_1845_Open_Text.style.display='none'; Codehighlighter1_1761_1845_Closed_Image.style.display='inline'; Codehighlighter1_1761_1845_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1761_1845_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1761_1845_Closed_Text.style.display='none'; Codehighlighter1_1761_1845_Open_Image.style.display='inline'; Codehighlighter1_1761_1845_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;NetComm_Close()&nbsp;</span><span id="Codehighlighter1_1761_1845_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1761_1845_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(sock&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_1790_1813_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1790_1813_Open_Text.style.display='none'; Codehighlighter1_1790_1813_Closed_Image.style.display='inline'; Codehighlighter1_1790_1813_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1790_1813_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1790_1813_Closed_Text.style.display='none'; Codehighlighter1_1790_1813_Open_Image.style.display='inline'; Codehighlighter1_1790_1813_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1790_1813_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1790_1813_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sock.close();<br />
<img id="Codehighlighter1_1837_1842_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1837_1842_Open_Text.style.display='none'; Codehighlighter1_1837_1842_Closed_Image.style.display='inline'; Codehighlighter1_1837_1842_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1837_1842_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1837_1842_Closed_Text.style.display='none'; Codehighlighter1_1837_1842_Open_Image.style.display='inline'; Codehighlighter1_1837_1842_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(IOException&nbsp;e)&nbsp;</span><span id="Codehighlighter1_1837_1842_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1837_1842_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1892_1972_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1892_1972_Open_Text.style.display='none'; Codehighlighter1_1892_1972_Closed_Image.style.display='inline'; Codehighlighter1_1892_1972_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1892_1972_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1892_1972_Closed_Text.style.display='none'; Codehighlighter1_1892_1972_Open_Image.style.display='inline'; Codehighlighter1_1892_1972_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;actionPerformed(ActionEvent&nbsp;e)&nbsp;</span><span id="Codehighlighter1_1892_1972_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1892_1972_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_1916_1939_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1916_1939_Open_Text.style.display='none'; Codehighlighter1_1916_1939_Closed_Image.style.display='inline'; Codehighlighter1_1916_1939_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1916_1939_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1916_1939_Closed_Text.style.display='none'; Codehighlighter1_1916_1939_Open_Image.style.display='inline'; Codehighlighter1_1916_1939_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(net_state&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1916_1939_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1916_1939_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NetComm_Init();<br />
<img id="Codehighlighter1_1946_1969_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1946_1969_Open_Text.style.display='none'; Codehighlighter1_1946_1969_Closed_Image.style.display='inline'; Codehighlighter1_1946_1969_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1946_1969_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1946_1969_Closed_Text.style.display='none'; Codehighlighter1_1946_1969_Open_Image.style.display='inline'; Codehighlighter1_1946_1969_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1946_1969_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1946_1969_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NetComm_Data();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<br />
<p>在以上程序中，也可以为外部应用提供一个回调函数，以便在网络异常或恢复正常时通知应用。服务应用的网络通信类类似，可以放在同一类中。</p>
<img src ="http://www.blogjava.net/jelver/aggbug/189060.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-27 16:58 <a href="http://www.blogjava.net/jelver/articles/189060.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实战体会Java的多线程编程  【转】</title><link>http://www.blogjava.net/jelver/articles/188126.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Mon, 24 Mar 2008 01:05:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/188126.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/188126.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/188126.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/188126.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/188126.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;在Java 程序中使用多线程要比在 C 或 C++ 中容易得多，这是因为 Java 编程语言提供了语言级的支持。本文通过简单的编程示例来说明 Java 程序中的多线程是多么直观。读完本文以后，用户应该能够编写简单的多线程程序。 　　为什么会排队等待？　　下面的这个简单的 Java 程序完成四项不相关的任务。这样的程序有单个控制线程，控制在这四个任务之间线性地移动。此外，...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/188126.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/188126.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-24 09:05 <a href="http://www.blogjava.net/jelver/articles/188126.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分层模式中的常见问题(zhuan)</title><link>http://www.blogjava.net/jelver/articles/186735.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Mon, 17 Mar 2008 05:14:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/186735.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/186735.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/186735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/186735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/186735.html</trackback:ping><description><![CDATA[<h1 style="margin: 17pt 0cm 16.5pt"><span style="font-family: 宋体">引言</span></h1>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体"><font size="3">分层结构是目前复杂应用系统开发时普遍使用的模式，软件中层之间的依赖关系约束是比较宽松的，并不要求上层仅可以依赖于直接下层，而是上层可以依赖于它的所有下层。</font></span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体"><font size="3">设计中我们会把各种系统的各种组件映射至不同层中，而在我所接触的一些实际项目中设计人员在映射这种组件和层间的关系时经常无意中破坏了层结构的依赖关系约束。</font></span></p>
<p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><font size="2"><span style="font-family: 黑体"><img height="456" alt="" src="http://www.java3z.com/cwbwebhome/article/article2/img6/1.jpg" width="187" /></span></font></p>
<p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><font size="2"><span style="font-family: 黑体">图表</span> 1<span style="font-family: 黑体">典型分层结构</span></font></p>
<h1 style="margin: 17pt 0cm 16.5pt"><span style="font-family: 宋体">设计中的常见问题</span></h1>
<h2 style="margin: 13pt 0cm"><span style="font-family: 黑体">问题一</span>:<span style="font-family: 黑体">数据传输对象（</span>DTO<span style="font-family: 黑体">）是否应该属于业务层？</span></h2>
<p style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体">在</span><font face="Times New Roman">J2EE</font><span style="font-family: 宋体">开发的经典著作《</span><font face="Times New Roman">Core J2EE Patterns</font><span style="font-family: 宋体">》中数据传输对象被划分在业务层模式中，那么是否数据传输对象应该被映射到业务层呢？</span></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体">数据访问对象（</span><font face="Times New Roman">DAO</font><span style="font-family: 宋体">）在该著作中是被映射到整合层的，这样就会出现一个违反层依赖约束的问题，因为数据访问对象是要依赖于数据传输对象的，因此下层就会出现对上层的依赖了。</span></font></p>
<p style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体">所以本人认为</span><font face="Times New Roman">DTO</font><span style="font-family: 宋体">是在各层中传输数据的，我们可以不必强求的把他们映射到上述层次中，可以把他们放置在一个公共包中。</span></font></p>
<h2 style="margin: 13pt 0cm"><span style="font-family: 黑体">问题二</span>:<span style="font-family: 黑体">使用</span>POJO<span style="font-family: 黑体">作业务对象的轻量级架构与上述层模型的映射</span></h2>
<p style="margin: 0cm 0cm 0pt"><font size="3"><span style="font-family: 宋体">在使用</span><font face="Times New Roman">POJO</font><span style="font-family: 宋体">的轻量级结构中我们通常会使用持久化框架（如</span><font face="Times New Roman">Hibernate/JPA</font><span style="font-family: 宋体">）同时会在架构中引入仓库对象</span><font face="Times New Roman">(Repository Object)</font><span style="font-family: 宋体">，负责业务对象的获取和保存。（注意：他的功能和</span><font face="Times New Roman">DAO</font><span style="font-family: 宋体">是有区别的，仓库对象中通常只应包括业务对象的获取和保存逻辑）。</span></font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体"><font size="3">通常设计人员会把业务对象映射至业务层，而将仓库对象映射至整合层。由于仓库对象对于业务对象的依赖关系就会破坏依赖关系约束，所以这种映射方式显然不正确。</font></span></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体"><font size="3">下图是作者推荐的映射方式</font></span></p>
<p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><font size="2"><span style="font-family: 黑体"><img height="761" alt="" src="http://www.java3z.com/cwbwebhome/article/article2/img6/2.jpg" width="470" /></span></font></p>
<p style="margin: 0cm 0cm 0pt; text-align: center" align="center"><font size="2"><span style="font-family: 黑体">图表</span> 2<span style="font-family: 黑体">轻量级架构参考模型</span></font></p>
<p style="margin: 0cm 0cm 0pt"><span style="font-family: 宋体"><font size="3">可以看到业务对象和仓库对象都被映射至业务层，而持久化框架被映射到了整合层。</font></span></p>
<h1 style="margin: 17pt 0cm 16.5pt"><span style="font-family: 宋体">总结</span></h1>
<p><span style="font-size: 10.5pt; font-family: 宋体">因此大家在设计过程中不要仅仅将分层结构留于形式，而要时刻注意设计是否符合这种架构模式，这样才能真正发挥这种架构模式的优势。</span>&nbsp;</p>
<img src ="http://www.blogjava.net/jelver/aggbug/186735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-17 13:14 <a href="http://www.blogjava.net/jelver/articles/186735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>线程同步 (转)</title><link>http://www.blogjava.net/jelver/articles/186530.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Sat, 15 Mar 2008 12:17:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/186530.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/186530.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/186530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/186530.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/186530.html</trackback:ping><description><![CDATA[<div id="related_topics" style="position: relative" _madepositioned="true" _eventid="2">原文:http://www.javaeye.com/topic/164905<br />
<br />
我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程（Thread）。 <br />
线程（Thread）是一份独立运行的程序，有自己专用的运行栈。线程有可能和其他线程共享一些资源，比如，内存，文件，数据库等。 <br />
当多个线程同时读写同一份共享资源的时候，可能会引起冲突。这时候，我们需要引入线程&#8220;同步&#8221;机制，即各位线程之间要有个先来后到，不能一窝蜂挤上去抢作一团。 <br />
同步这个词是从英文synchronize（使同时发生）翻译过来的。我也不明白为什么要用这个很容易引起误解的词。既然大家都这么用，咱们也就只好这么将就。 <br />
线程同步的真实意思和字面意思恰好相反。线程同步的真实意思，其实是&#8220;排队&#8221;：几个线程之间要排队，一个一个对共享资源进行操作，而不是同时进行操作。 <br />
<br />
因此，关于线程同步，需要牢牢记住的第一点是：线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程&#8220;同步&#8221;执行。这可真是个无聊的绕口令。 <br />
关于线程同步，需要牢牢记住的第二点是 &#8220;共享&#8221;这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源，那么就根本没有同步的必要。 <br />
关于线程同步，需要牢牢记住的第三点是，只有&#8220;变量&#8221;才需要同步访问。如果共享的资源是固定不变的，那么就相当于&#8220;常量&#8221;，线程同时读取常量也不需要同步。至少一个线程修改共享资源，这样的情况下，线程之间就需要同步。 <br />
关于线程同步，需要牢牢记住的第四点是：多个线程访问共享资源的代码有可能是同一份代码，也有可能是不同的代码；无论是否执行同一份代码，只要这些线程的代码访问同一份可变的共享资源，这些线程之间就需要同步。 <br />
<br />
为了加深理解，下面举几个例子。 <br />
有两个采购员，他们的工作内容是相同的，都是遵循如下的步骤： <br />
（1）到市场上去，寻找并购买有潜力的样品。 <br />
（2）回到公司，写报告。 <br />
这两个人的工作内容虽然一样，他们都需要购买样品，他们可能买到同样种类的样品，但是他们绝对不会购买到同一件样品，他们之间没有任何共享资源。所以，他们可以各自进行自己的工作，互不干扰。 <br />
这两个采购员就相当于两个线程；两个采购员遵循相同的工作步骤，相当于这两个线程执行同一段代码。 <br />
<br />
下面给这两个采购员增加一个工作步骤。采购员需要根据公司的&#8220;布告栏&#8221;上面公布的信息，安排自己的工作计划。 <br />
这两个采购员有可能同时走到布告栏的前面，同时观看布告栏上的信息。这一点问题都没有。因为布告栏是只读的，这两个采购员谁都不会去修改布告栏上写的信息。 <br />
<br />
下面增加一个角色。一个办公室行政人员这个时候，也走到了布告栏前面，准备修改布告栏上的信息。 <br />
如果行政人员先到达布告栏，并且正在修改布告栏的内容。两个采购员这个时候，恰好也到了。这两个采购员就必须等待行政人员完成修改之后，才能观看修改后的信息。 <br />
如果行政人员到达的时候，两个采购员已经在观看布告栏了。那么行政人员需要等待两个采购员把当前信息记录下来之后，才能够写上新的信息。 <br />
上述这两种情况，行政人员和采购员对布告栏的访问就需要进行同步。因为其中一个线程（行政人员）修改了共享资源（布告栏）。而且我们可以看到，行政人员的工作流程和采购员的工作流程（执行代码）完全不同，但是由于他们访问了同一份可变共享资源（布告栏），所以他们之间需要同步。 <br />
<br />
同步锁 <br />
<br />
前面讲了为什么要线程同步，下面我们就来看如何才能线程同步。 <br />
线程同步的基本实现思路还是比较容易理解的。我们可以给共享资源加一把锁，这把锁只有一把钥匙。哪个线程获取了这把钥匙，才有权利访问该共享资源。 <br />
生活中，我们也可能会遇到这样的例子。一些超市的外面提供了一些自动储物箱。每个储物箱都有一把锁，一把钥匙。人们可以使用那些带有钥匙的储物箱，把东西放到储物箱里面，把储物箱锁上，然后把钥匙拿走。这样，该储物箱就被锁住了，其他人不能再访问这个储物箱。（当然，真实的储物箱钥匙是可以被人拿走复制的，所以不要把贵重物品放在超市的储物箱里面。于是很多超市都采用了电子密码锁。） <br />
线程同步锁这个模型看起来很直观。但是，还有一个严峻的问题没有解决，这个同步锁应该加在哪里？ <br />
当然是加在共享资源上了。反应快的读者一定会抢先回答。 <br />
没错，如果可能，我们当然尽量把同步锁加在共享资源上。一些比较完善的共享资源，比如，文件系统，数据库系统等，自身都提供了比较完善的同步锁机制。我们不用另外给这些资源加锁，这些资源自己就有锁。 <br />
但是，大部分情况下，我们在代码中访问的共享资源都是比较简单的共享对象。这些对象里面没有地方让我们加锁。 <br />
读者可能会提出建议：为什么不在每一个对象内部都增加一个新的区域，专门用来加锁呢？这种设计理论上当然也是可行的。问题在于，线程同步的情况并不是很普遍。如果因为这小概率事件，在所有对象内部都开辟一块锁空间，将会带来极大的空间浪费。得不偿失。 <br />
于是，现代的编程语言的设计思路都是把同步锁加在代码段上。确切的说，是把同步锁加在&#8220;访问共享资源的代码段&#8221;上。这一点一定要记住，同步锁是加在代码段上的。 <br />
同步锁加在代码段上，就很好地解决了上述的空间浪费问题。但是却增加了模型的复杂度，也增加了我们的理解难度。 <br />
现在我们就来仔细分析&#8220;同步锁加在代码段上&#8221;的线程同步模型。 <br />
首先，我们已经解决了同步锁加在哪里的问题。我们已经确定，同步锁不是加在共享资源上，而是加在访问共享资源的代码段上。 <br />
其次，我们要解决的问题是，我们应该在代码段上加什么样的锁。这个问题是重点中的重点。这是我们尤其要注意的问题：访问同一份共享资源的不同代码段，应该加上同一个同步锁；如果加的是不同的同步锁，那么根本就起不到同步的作用，没有任何意义。 <br />
这就是说，同步锁本身也一定是多个线程之间的共享对象。 <br />
<br />
Java语言的synchronized关键字 <br />
<br />
为了加深理解，举几个代码段同步的例子。 <br />
不同语言的同步锁模型都是一样的。只是表达方式有些不同。这里我们以当前最流行的Java语言为例。Java语言里面用synchronized关键字给代码段加锁。整个语法形式表现为 <br />
synchronized(同步锁) { <br />
// 访问共享资源，需要同步的代码段 <br />
} <br />
<br />
这里尤其要注意的就是，同步锁本身一定要是共享的对象。 <br />
<br />
&#8230; f1() { <br />
<br />
Object lock1 = new Object(); // 产生一个同步锁 <br />
<br />
synchronized(lock1){ <br />
// 代码段 A <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
上面这段代码没有任何意义。因为那个同步锁是在函数体内部产生的。每个线程调用这段代码的时候，都会产生一个新的同步锁。那么多个线程之间，使用的是不同的同步锁。根本达不到同步的目的。 <br />
同步代码一定要写成如下的形式，才有意义。 <br />
<br />
public static final Object lock1 = new Object(); <br />
<br />
&#8230; f1() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 A <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
<br />
你不一定要把同步锁声明为static或者public，但是你一定要保证相关的同步代码之间，一定要使用同一个同步锁。 <br />
讲到这里，你一定会好奇，这个同步锁到底是个什么东西。为什么随便声明一个Object对象，就可以作为同步锁？ <br />
在Java里面，同步锁的概念就是这样的。任何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配系统中的内存地址。因此，要保证同步代码段之间使用的是同一个同步锁，我们就要保证这些同步代码段的synchronized关键字使用的是同一个Object Reference，同一个内存地址。这也是为什么我在前面的代码中声明lock1的时候，使用了final关键字，这就是为了保证lock1的Object Reference在整个系统运行过程中都保持不变。 <br />
一些求知欲强的读者可能想要继续深入了解synchronzied(同步锁)的实际运行机制。Java虚拟机规范中（你可以在google用&#8220;JVM Spec&#8221;等关键字进行搜索），有对synchronized关键字的详细解释。synchronized会编译成 monitor enter, &#8230; monitor exit之类的指令对。Monitor就是实际上的同步锁。每一个Object Reference在概念上都对应一个monitor。 <br />
这些实现细节问题，并不是理解同步锁模型的关键。我们继续看几个例子，加深对同步锁模型的理解。 <br />
<br />
public static final Object lock1 = new Object(); <br />
<br />
&#8230; f1() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 A <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
&#8230; f2() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 B <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
上述的代码中，代码段A和代码段B就是同步的。因为它们使用的是同一个同步锁lock1。 <br />
如果有10个线程同时执行代码段A，同时还有20个线程同时执行代码段B，那么这30个线程之间都是要进行同步的。 <br />
这30个线程都要竞争一个同步锁lock1。同一时刻，只有一个线程能够获得lock1的所有权，只有一个线程可以执行代码段A或者代码段B。其他竞争失败的线程只能暂停运行，进入到该同步锁的就绪（Ready）队列。 <br />
每一个同步锁下面都挂了几个线程队列，包括就绪（Ready）队列，待召（Waiting）队列等。比如，lock1对应的就绪队列就可以叫做lock1 - ready queue。每个队列里面都可能有多个暂停运行的线程。 <br />
注意，竞争同步锁失败的线程进入的是该同步锁的就绪（Ready）队列，而不是后面要讲述的待召队列（Waiting Queue，也可以翻译为等待队列）。就绪队列里面的线程总是时刻准备着竞争同步锁，时刻准备着运行。而待召队列里面的线程则只能一直等待，直到等到某个信号的通知之后，才能够转移到就绪队列中，准备运行。 <br />
成功获取同步锁的线程，执行完同步代码段之后，会释放同步锁。该同步锁的就绪队列中的其他线程就继续下一轮同步锁的竞争。成功者就可以继续运行，失败者还是要乖乖地待在就绪队列中。 <br />
因此，线程同步是非常耗费资源的一种操作。我们要尽量控制线程同步的代码段范围。同步的代码段范围越小越好。我们用一个名词&#8220;同步粒度&#8221;来表示同步代码段的范围。 <br />
同步粒度 <br />
在Java语言里面，我们可以直接把synchronized关键字直接加在函数的定义上。 <br />
比如。 <br />
&#8230; synchronized &#8230; f1() { <br />
// f1 代码段 <br />
} <br />
<br />
这段代码就等价于 <br />
&#8230; f1() { <br />
synchronized(this){ // 同步锁就是对象本身 <br />
// f1 代码段 <br />
} <br />
} <br />
<br />
同样的原则适用于静态（static）函数 <br />
比如。 <br />
&#8230; static synchronized &#8230; f1() { <br />
// f1 代码段 <br />
} <br />
<br />
这段代码就等价于 <br />
&#8230;static &#8230; f1() { <br />
synchronized(Class.forName(&#8230;)){ // 同步锁是类定义本身 <br />
// f1 代码段 <br />
} <br />
} <br />
<br />
但是，我们要尽量避免这种直接把synchronized加在函数定义上的偷懒做法。因为我们要控制同步粒度。同步的代码段越小越好。synchronized控制的范围越小越好。 <br />
我们不仅要在缩小同步代码段的长度上下功夫，我们同时还要注意细分同步锁。 <br />
比如，下面的代码 <br />
<br />
public static final Object lock1 = new Object(); <br />
<br />
&#8230; f1() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 A <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
&#8230; f2() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 B <br />
// 访问共享资源 resource1 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
&#8230; f3() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 C <br />
// 访问共享资源 resource2 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
&#8230; f4() { <br />
<br />
synchronized(lock1){ // lock1 是公用同步锁 <br />
// 代码段 D <br />
// 访问共享资源 resource2 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
上述的4段同步代码，使用同一个同步锁lock1。所有调用4段代码中任何一段代码的线程，都需要竞争同一个同步锁lock1。 <br />
我们仔细分析一下，发现这是没有必要的。 <br />
因为f1()的代码段A和f2()的代码段B访问的共享资源是resource1，f3()的代码段C和f4()的代码段D访问的共享资源是resource2，它们没有必要都竞争同一个同步锁lock1。我们可以增加一个同步锁lock2。f3()和f4()的代码可以修改为： <br />
public static final Object lock2 = new Object(); <br />
<br />
&#8230; f3() { <br />
<br />
synchronized(lock2){ // lock2 是公用同步锁 <br />
// 代码段 C <br />
// 访问共享资源 resource2 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
&#8230; f4() { <br />
<br />
synchronized(lock2){ // lock2 是公用同步锁 <br />
// 代码段 D <br />
// 访问共享资源 resource2 <br />
// 需要同步 <br />
} <br />
} <br />
<br />
这样，f1()和f2()就会竞争lock1，而f3()和f4()就会竞争lock2。这样，分开来分别竞争两个锁，就可以大大较少同步锁竞争的概率，从而减少系统的开销。 <br />
<br />
信号量 <br />
<br />
同步锁模型只是最简单的同步模型。同一时刻，只有一个线程能够运行同步代码。 <br />
有的时候，我们希望处理更加复杂的同步模型，比如生产者/消费者模型、读写同步模型等。这种情况下，同步锁模型就不够用了。我们需要一个新的模型。这就是我们要讲述的信号量模型。 <br />
信号量模型的工作方式如下：线程在运行的过程中，可以主动停下来，等待某个信号量的通知；这时候，该线程就进入到该信号量的待召（Waiting）队列当中；等到通知之后，再继续运行。 <br />
很多语言里面，同步锁都由专门的对象表示，对象名通常叫Monitor。 <br />
同样，在很多语言中，信号量通常也有专门的对象名来表示，比如，Mutex，Semphore。 <br />
信号量模型要比同步锁模型复杂许多。一些系统中，信号量甚至可以跨进程进行同步。另外一些信号量甚至还有计数功能，能够控制同时运行的线程数。 <br />
我们没有必要考虑那么复杂的模型。所有那些复杂的模型，都是最基本的模型衍生出来的。只要掌握了最基本的信号量模型——&#8220;等待/通知&#8221;模型，复杂模型也就迎刃而解了。 <br />
我们还是以Java语言为例。Java语言里面的同步锁和信号量概念都非常模糊，没有专门的对象名词来表示同步锁和信号量，只有两个同步锁相关的关键字——volatile和synchronized。 <br />
这种模糊虽然导致概念不清，但同时也避免了Monitor、Mutex、Semphore等名词带来的种种误解。我们不必执着于名词之争，可以专注于理解实际的运行原理。 <br />
在Java语言里面，任何一个Object Reference都可以作为同步锁。同样的道理，任何一个Object Reference也可以作为信号量。 <br />
Object对象的wait()方法就是等待通知，Object对象的notify()方法就是发出通知。 <br />
具体调用方法为 <br />
（1）等待某个信号量的通知 <br />
public static final Object signal = new Object(); <br />
<br />
&#8230; f1() { <br />
synchronized(singal) { // 首先我们要获取这个信号量。这个信号量同时也是一个同步锁 <br />
<br />
// 只有成功获取了signal这个信号量兼同步锁之后，我们才可能进入这段代码 <br />
signal.wait(); // 这里要放弃信号量。本线程要进入signal信号量的待召（Waiting）队列 <br />
<br />
// 可怜。辛辛苦苦争取到手的信号量，就这么被放弃了 <br />
<br />
// 等到通知之后，从待召（Waiting）队列转到就绪（Ready）队列里面 <br />
// 转到了就绪队列中，离CPU核心近了一步，就有机会继续执行下面的代码了。 <br />
// 仍然需要把signal同步锁竞争到手，才能够真正继续执行下面的代码。命苦啊。 <br />
&#8230; <br />
} <br />
} <br />
<br />
需要注意的是，上述代码中的signal.wait()的意思。signal.wait()很容易导致误解。signal.wait()的意思并不是说，signal开始wait，而是说，运行这段代码的当前线程开始wait这个signal对象，即进入signal对象的待召（Waiting）队列。 <br />
<br />
（2）发出某个信号量的通知 <br />
&#8230; f2() { <br />
synchronized(singal) { // 首先，我们同样要获取这个信号量。同时也是一个同步锁。 <br />
<br />
// 只有成功获取了signal这个信号量兼同步锁之后，我们才可能进入这段代码 <br />
signal.notify(); // 这里，我们通知signal的待召队列中的某个线程。 <br />
<br />
// 如果某个线程等到了这个通知，那个线程就会转到就绪队列中 <br />
// 但是本线程仍然继续拥有signal这个同步锁，本线程仍然继续执行 <br />
// 嘿嘿，虽然本线程好心通知其他线程， <br />
// 但是，本线程可没有那么高风亮节，放弃到手的同步锁 <br />
// 本线程继续执行下面的代码 <br />
&#8230; <br />
} <br />
} <br />
<br />
需要注意的是，signal.notify()的意思。signal.notify()并不是通知signal这个对象本身。而是通知正在等待signal信号量的其他线程。 <br />
<br />
以上就是Object的wait()和notify()的基本用法。 <br />
实际上，wait()还可以定义等待时间，当线程在某信号量的待召队列中，等到足够长的时间，就会等无可等，无需再等，自己就从待召队列转移到就绪队列中了。 <br />
另外，还有一个notifyAll()方法，表示通知待召队列里面的所有线程。 <br />
这些细节问题，并不对大局产生影响。 <br />
<br />
绿色线程 <br />
<br />
绿色线程（Green Thread）是一个相对于操作系统线程（Native Thread）的概念。 <br />
操作系统线程（Native Thread）的意思就是，程序里面的线程会真正映射到操作系统的线程，线程的运行和调度都是由操作系统控制的 <br />
绿色线程（Green Thread）的意思是，程序里面的线程不会真正映射到操作系统的线程，而是由语言运行平台自身来调度。 <br />
当前版本的Python语言的线程就可以映射到操作系统线程。当前版本的Ruby语言的线程就属于绿色线程，无法映射到操作系统的线程，因此Ruby语言的线程的运行速度比较慢。 <br />
难道说，绿色线程要比操作系统线程要慢吗？当然不是这样。事实上，情况可能正好相反。Ruby是一个特殊的例子。线程调度器并不是很成熟。 <br />
目前，线程的流行实现模型就是绿色线程。比如，stackless Python，就引入了更加轻量的绿色线程概念。在线程并发编程方面，无论是运行速度还是并发负载上，都优于Python。 <br />
另一个更著名的例子就是ErLang（爱立信公司开发的一种开源语言）。 <br />
ErLang的绿色线程概念非常彻底。ErLang的线程不叫Thread，而是叫做Process。这很容易和进程混淆起来。这里要注意区分一下。 <br />
ErLang Process之间根本就不需要同步。因为ErLang语言的所有变量都是final的，不允许变量的值发生任何变化。因此根本就不需要同步。 <br />
final变量的另一个好处就是，对象之间不可能出现交叉引用，不可能构成一种环状的关联，对象之间的关联都是单向的，树状的。因此，内存垃圾回收的算法效率也非常高。这就让ErLang能够达到Soft Real Time（软实时）的效果。这对于一门支持内存垃圾回收的语言来说，可不是一件容易的事情。 </div>
<img src ="http://www.blogjava.net/jelver/aggbug/186530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-15 20:17 <a href="http://www.blogjava.net/jelver/articles/186530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常用的多线程异步处理</title><link>http://www.blogjava.net/jelver/articles/184502.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Fri, 07 Mar 2008 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/184502.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/184502.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/184502.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/184502.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/184502.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: package&nbsp;cn.allinpalm.sns.app.web.point.action;import&nbsp;java.util.LinkedList;import&nbsp;org.apache.log4j.Logger;import&nbsp;cn.allinpalm.sns.app.web.constants.Config;import&nbsp;cn...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/184502.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/184502.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-07 14:13 <a href="http://www.blogjava.net/jelver/articles/184502.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员面试题（转）</title><link>http://www.blogjava.net/jelver/articles/183353.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Mon, 03 Mar 2008 01:02:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/183353.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/183353.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/183353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/183353.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/183353.html</trackback:ping><description><![CDATA[答题时间20分钟 <br />
1. <br />
System.out.println(1+&#8217;\002&#8217;)会打印出多少? ___8进制______ <br />
System.out.println(1+2+&#8221;3&#8221;)会打印出多少? _________ <br />
<br />
2. 请简单补充完下面jdbc读取数据的实现 <br />
String SQL = &#8220;SELECT id , title, description FROM t_blog WHERE id = ?&#8221;; <br />
long id; <br />
String title; <br />
String description; <br />
Connection conn = null;//假设用ConnectionManager.getConnection();可以获得连接对象 <br />
PrepareStatement pstmt = null; <br />
<br />
<br />
<br />
如果description字段在数据库中是text类型，而且存储的文字比较多（20K左右），这时候该如何优化读取，让系统支撑更大的并发？ <br />
<br />
3. 有一篇文章的URL为 view.jsp?id=100 ，每分钟访问量可能上千次，在记录和显示它的查看次数时，你觉得如何做性能比较好？ <br />
<br />
4. 写出你最常见到的一些运行时异常(runtime exception)，再简述一下你是如何避免java 中空指针异常的 <br />
<br />
5. 你用lucene做过全文检索吗? 简单描述一下你的经验。<br />
<br />
6. 简述一下你对GC的理解，以及如何避免内存泄露。 <br />
<br />
7. 要求最后打印出的全部是数字，下面的程序满足要求吗？还可以再优化吗？请简单描述。 <br />
String strA = &#8220;1:2:3:4:5:6:7:8:9:10:&#8221;; <br />
String arrA[] = strA.split(&#8220;:&#8221;); <br />
for(int i=0;i&lt;arrA.length;i++) <br />
{ <br />
System.out.println(arrA[i]); <br />
} <br />
<br />
8. 简述一下javascript/dhtml/css/ajax在你以前项目中的应用程度；熟悉跨浏览器兼容javascript/css吗? 有兴趣对它们进行深入研究吗？ <br />
<br />
<br />
9. 你最熟悉Web开发过程中的哪部分？&gt; <br />
<img src ="http://www.blogjava.net/jelver/aggbug/183353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-03-03 09:02 <a href="http://www.blogjava.net/jelver/articles/183353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK1.5中引入了对java语言的多种扩展</title><link>http://www.blogjava.net/jelver/articles/180749.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 19 Feb 2008 14:11:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/180749.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/180749.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/180749.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/180749.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/180749.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JDK1.5中引入了对java语言的多种扩展，泛型(generics)即其中之一。这个教程的目标是向您介绍java的泛型(generic)。你可能熟悉其他语言的泛型，最著名的是C++的模板(templates)。如果这样，你很快就会看到两者的相似之处和重要差异。如果你不熟悉相似的语法结构，那么更好，你可以从头开始而不需要忘记误解。Generics允许对类型进行抽象(abstract ove...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/180749.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/180749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-02-19 22:11 <a href="http://www.blogjava.net/jelver/articles/180749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>泛型是J2SE 5.0最重要的特性</title><link>http://www.blogjava.net/jelver/articles/180746.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 19 Feb 2008 14:08:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/180746.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/180746.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/180746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/180746.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/180746.html</trackback:ping><description><![CDATA[英文原文地址:<br />
<a href="http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html" target="_new">http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html</a><br />
中文地址:<br />
<a href="http://www.matrix.org.cn/resource/article/43/43634_java_generics.html" target="_new">http://www.matrix.org.cn/resource/article/43/43634_java_generics.html</a><br />
关键词： java generics java5<br />
<br />
<strong>摘要</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 泛型是J2SE 5.0最重要的特性。他们让你写一个type(类或接口）和创建一个实例通过传递一个或多个引用类型。这个实例受限于只能作用于这些类型。比如，在java 5，java.util.List 已经被泛化。当建立一个list对象时，你通过传递一个java类型建立一个List实例，此list实例只能作用于所传递的类型。这意味着如果你传递一个String ,此List实例只能拥有String对象；如果你传递一个Integer，此实例只能存贮Integer对象。除了创建参数化的类型，你还能创建参数化的函数。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 泛型的第一个好处是编译时的严格类型检查。这是集合框架最重要的特点。此外,泛型消除了绝大多数的类型转换。在JDK 5.0之前，当你使用集合框架时，你不得不进行类型转换。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 本文将教你如何操作泛型。它的第一部分是&#8220;没有泛型的日子&#8221;，先让我们回忆老版本JDK的不便。然后，举一些泛型的例子。在讨论完语法以及有界泛型的使用之后，文章最后一章将解释如何写泛型。<br />
&nbsp;&nbsp;<br />
<br />
<strong>没有泛型的日子</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp; 所有的java类都源自java.lang.Object,这意味着所有的JAVA对象能转换成Object。因此，在之前的JDK的版本中，很多集合框架的函数接受一个Object参数。所以，collections是一个能持有任何对象的多用途工具，但带来了不良的后果。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 举个简单的例子，在JDK 5.0的之前版本中，类List的函数add接受一个Object参数：<br />
<br />
<pre class="overflow" title="pre code">public boolean add(java.lang.Object element)</pre>
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所以你能传递任何类型给add。这是故意这么设计的。否则，它只能传递某种特定的对象，这样就会出现各种List类型，如，StringList, EmployeeList, AddressList等。<br />
&nbsp;&nbsp;&nbsp;&nbsp; add通过Object传递能带来好处,现在我们考虑get函数(返回List中的一个元素).如下是JDK 5之前版本的定义：<br />
<br />
<pre class="overflow" title="pre code">public java.lang.Object get(int index) throws IndexOutOfBoundsException</pre>
<br />
<br />
get返回一个Object.不幸的事情从此开始了.假如你储存了两个String对象在一个List中:<br />
<br />
<pre class="overflow" title="pre code">List stringList1 = new ArrayList();<br />
stringList1.add("Java 5");<br />
stringList1.add("with generics");</pre>
<br />
<br />
当你想从stringList1取得一个元素时,你得到了一个Object.为了操作原来的类型元素,你不得不把它转换为String。<br />
<br />
<pre class="overflow" title="pre code">String s1 = (String) stringList1.get(0);</pre>
<br />
<br />
但是,假如你曾经把一个非String对象加入stringList1中,上面的代码会抛出一个ClassCastException. 有了泛型,你能创建一个单一用途的List实例.比如,你能创建一个只接受String对象的List实例,另外一个实例只能接受Employee对象.这同样适用于集合框架中的其他类型.<br />
<br />
<br />
<strong>泛型入门</strong><br />
<br />
&nbsp;&nbsp; 像一个函数能接受参数一样,一个泛型也能接受参数.这就是一个泛型经常被称为一个参数化类型的原因.但是不像函数用()传递参数,泛型是用&lt;&gt;传递参数的.声明一个泛型和声明一个普通类没有什么区别,只不过你把泛型的变量放在&lt;&gt;中.<br />
&nbsp;&nbsp;&nbsp;&nbsp; 比如,在JDK 5中,你可以这样声明一个java.util.List :&nbsp;&nbsp;List&lt;E&gt; myList;<br />
E 称为类型变量.意味着一个变量将被一个类型替代.替代类型变量的值将被当作参数或返回类型.对于List接口来说,当一个实例被创建以后,E 将被当作一个add或别的函数的参数.E 也会使get或别的参数的返回值.下面是add和get的定义:<br />
<br />
<pre class="overflow" title="pre code">boolean add&lt;E o&gt;<br />
E get(int index)</pre>
<br />
<br />
<span style="color: red">NOTE:</span>一个泛型在声明或例示时允许你传递特定的类型变量: E.除此之外,如果E是个类，你可以传递子类；如果E是个接口，你可以传递实现接口的类；<br />
<br />
<span style="color: purple">-----------------------------译者添加--------------------<br />
List&lt;Number&gt; numberList= new ArrayList&lt;Number&gt;();<br />
&nbsp;&nbsp; numberList.add(2.0);<br />
&nbsp;&nbsp; numberList.add(2);<br />
-----------------------------译者添加--------------------</span><br />
<br />
如果你传递一个String给一个List，比如：<br />
<br />
<pre class="overflow" title="pre code">List&lt;String&gt; myList;</pre>
<br />
<br />
那么mylist的add函数将接受一个String作为他的参数，而get函数将返回一个String.因为返回了一个特定的类型，所以不用类型转化了。<br />
<br />
<span style="color: red">NOTE</span>：根据惯例，我们使用一个唯一的大写字目表示一个类型变量。为了创建一个泛型，你需在声明时传递同样的参数列表。比如，你要想创建一个ArrayList来操作String ，你必须把String放在&lt;&gt;中。如：<br />
<br />
<pre class="overflow" title="pre code">List&lt;String&gt; myList = new ArrayList&lt;String&gt;();</pre>
<br />
<br />
再比如，java.util.Map 是这么定义的：<br />
<br />
<pre class="overflow" title="pre code">public interface Map&lt;K,V&gt;</pre>
<br />
<br />
K用来声明map键(KEY)的类型而V用来表示值(VALUE)的类型。put和values是这么定义的：<br />
<br />
<pre class="overflow" title="pre code">V put(K key, V value)<br />
Collection&lt;V&gt; values()</pre>
<br />
<br />
<span style="color: red">NOTE</span>:一个泛型不准直接的或间接的是java.lang.Throwable的子类。因为异常是在运行时抛出的,所以它不可能预言什么类型的异常将在编译时抛出.<br />
<br />
列表1的例子将比较List在JDK 1.4 和JDK1.5的不同<br />
<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.List;<br />
import java.util.ArrayList;<br />
<br />
public class GenericListTest {<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// in JDK 1.4<br />
&nbsp;&nbsp;&nbsp;&nbsp;List stringList1 = new ArrayList();<br />
&nbsp;&nbsp;&nbsp;&nbsp;stringList1.add("Java 1.0 - 5.0");<br />
&nbsp;&nbsp;&nbsp;&nbsp;stringList1.add("without generics");<br />
&nbsp;&nbsp;&nbsp;&nbsp;// cast to java.lang.String<br />
&nbsp;&nbsp;&nbsp;&nbsp;String s1 = (String) stringList1.get(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s1.toUpperCase());<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;// now with generics in JDK 5<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt; stringList2 = new ArrayList&lt;String&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;stringList2.add("Java 5.0");<br />
&nbsp;&nbsp;&nbsp;&nbsp;stringList2.add("with generics");<br />
&nbsp;&nbsp;&nbsp;&nbsp;// no need for type casting<br />
&nbsp;&nbsp;&nbsp;&nbsp;String s2 = stringList2.get(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s2.toUpperCase());<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
<br />
在列表1中，stringList2是个泛型。声明List&lt;String&gt;告诉编译器List的实例能接受一个String对象。当然，在另外的情况中，你能新建能接受各种对象的List实例。注意，当从List实例中返回成员元素时，不需要对象转化，因为他返回的了你想要的类型，也就是String.<br />
<br />
<span style="color: red">NOTE</span>:泛型的类型检查(type checking)是在编译时完成的.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最让人感兴趣的事情是，一个泛型是个类型并且能被当作一个类型变量。比如，你想你的List储存lists of Strings,你能通过把List&lt;String&gt;作为他的类型变量来声明List。比如：<br />
<br />
<pre class="overflow" title="pre code">List&lt;List&lt;String&gt;&gt; myListOfListsOfStrings;</pre>
<br />
<br />
要从myList中的第一个List重新取得String，你可以这么用：<br />
<br />
<pre class="overflow" title="pre code">String s = myListOfListsOfStrings.get(0).get(0);</pre>
<br />
<br />
下一个列表中的ListOfListsTest类示范了一个List（命名为listOfLists）接受一个String List作为参数。<br />
<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.ArrayList;<br />
import java.util.List;<br />
public class ListOfListsTest {<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt; listOfStrings = new ArrayList&lt;String&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;listOfStrings.add("Hello again");<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;List&lt;String&gt;&gt; listOfLists = new ArrayList&lt;List&lt;String&gt;&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;listOfLists.add(listOfStrings);<br />
&nbsp;&nbsp;&nbsp;&nbsp;String s = listOfLists.get(0).get(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s); // prints "Hello again"<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
<br />
另外，一个泛型接受一个或多个类型变量。比如，java.util.Map有两个类型变量s。第一个定义了键（key）的类型，第二个定义了值（value)的类型。下面的例子讲教我们如何使用个一个泛型Map.<br />
<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
public class MapTest {<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;String, String&gt; map = new HashMap&lt;String, String&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put("key1", "value1");<br />
&nbsp;&nbsp;&nbsp;&nbsp;map.put("key2", "value2");<br />
&nbsp;&nbsp;&nbsp;&nbsp;String value1 = map.get("key1");<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
<br />
在这个例子中，重新得到一个key1代表的String值，我们不需要任何类型转换。<br />
<br />
<strong>没有参数的情况下使用泛型</strong><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;既然在J2SE 5.0中收集类型已经泛型化，那么，原来的使用这些类型的代码将如何呢？很幸运，他们在JAVA 5中将继续工作，因为你能使用没有参数的泛型。比如，你能继续像原来一样使用List接口，正如下面的例子一样。<br />
<br />
<pre class="overflow" title="pre code">List stringList1 = new ArrayList();<br />
stringList1.add("Java 1.0 - 5.0");<br />
stringList1.add("without generics");<br />
String s1 = (String) stringList1.get(0);</pre>
<br />
<br />
一个没有任何参数的泛型被称为原型(raw type)。它意味着这些为JDK1.4或更早的版本而写的代码将继续在java 5中工作。<br />
<br />
尽管如此，一个需要注意的事情是，JDK５编译器希望你使用带参数的泛型。否则，编译器将提示警告，因为他认为你可能忘了定义类型变量s。比如，编译上面的代码的时候你会看到下面这些警告，因为第一个List被认为是原型。<br />
<br />
Note: com/brainysoftware/jdk5/app16/GenericListTest.java<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uses unchecked or unsafe operations.<br />
Note: Recompile with -Xlint:unchecked for details.<br />
<br />
当你使用原型时，如果你不想看到这些警告，你有几个选择来达到目的：<br />
1.编译时带上参数-source 1.4<br />
2.使用@SupressWarnings("unchecked")注释<br />
3.更新你的代码，使用List&lt;Object&gt;. List&lt;Object&gt;的实例能接受任何类型的对象，就像是一个原型List。然而，编译器不会报错。<br />
<br />
<strong>使用 ？ 通配符</strong><br />
&nbsp;&nbsp; 前面提过，如果你声明了一个List&lt;aType&gt;, 那么这个List对aType起作用，所以你能储存下面这些类型的对象：<br />
1.一个aType的实例<br />
2.它的子类的实例(如果aType是个类)<br />
3.实现aType接口的类实例(如果aType是个接口)<br />
但是，请注意，一个泛型本身是个JAVA类型，就像java.lang.String或java.io.File一样。传递不同的类型变量给泛型可以创建不同的JAVA类型。比如，下面例子中list1和list2引用了不同的类型对象。<br />
<br />
<pre class="overflow" title="pre code">List&lt;Object&gt; list1 = new ArrayList&lt;Object&gt;();<br />
List&lt;String&gt; list2 = new ArrayList&lt;String&gt;();</pre>
<br />
<br />
list1指向了一个类型变量s为java.lang.Objects 的List而list2指向了一个类型变量s为String 的List。所以传递一个List&lt;String&gt;给一个参数为List&lt;Object&gt;的函数将导致compile time错误。下面列表可以说明：<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.ArrayList;<br />
import java.util.List;<br />
<br />
public class AllowedTypeTest {<br />
&nbsp;&nbsp;public static void doIt(List&lt;Object&gt; l) {<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt; myList = new ArrayList&lt;String&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 这里将产生一个错误<br />
&nbsp;&nbsp;&nbsp;&nbsp;doIt(myList);<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
上面的代码无法编译，因为你试图传递一个错误的类型给函数doIt。doIt的参数是List&lt;Object&gt;二你传递的参数是List&lt;String&gt;。<br />
可以使用 ？ 通配符解决这个难题。List&lt;?&gt; 意味着一个对任何对象起作用的List。所以，doIt可以改为：<br />
<br />
<pre class="overflow" title="pre code">public static void doIt(List&lt;?&gt; l) {}</pre>
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;在某些情况下你会考虑使用 ? 通配符。比如，你有一个printList函数，这个函数打印一个List的所有成员，你想让这个函数对任何类型的List起作用时。否则，你只能累死累活的写很多printList的重载函数。下面的列表引用了使用 ? 通配符的printList函数。<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.ArrayList;<br />
import java.util.List;<br />
<br />
public class WildCardTest {<br />
<br />
&nbsp;&nbsp;public static void printList(List&lt;?&gt; list) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (Object element : list) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(element);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;String&gt; list1 = new ArrayList&lt;String&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;list1.add("Hello");<br />
&nbsp;&nbsp;&nbsp;&nbsp;list1.add("World");<br />
&nbsp;&nbsp;&nbsp;&nbsp;printList(list1);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Integer&gt; list2 = new ArrayList&lt;Integer&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;list2.add(100);<br />
&nbsp;&nbsp;&nbsp;&nbsp;list2.add(200);<br />
&nbsp;&nbsp;&nbsp;&nbsp;printList(list2);<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
<br />
这些代码说明了在printList函数中，List&lt;?&gt;表示各种类型的List对象。然而，请注意，在声明的时候使用 ? 通配符是不合法的，像这样：<br />
<br />
<pre class="overflow" title="pre code">List&lt;?&gt; myList = new ArrayList&lt;?&gt;(); // 不合法</pre>
<br />
<br />
如果你想创建一个接收任何类型对象的List，你可以使用Object作为类型变量，就像这样：<br />
<br />
<pre class="overflow" title="pre code">List&lt;Object&gt; myList = new ArrayList&lt;Object&gt;();</pre>
<br />
<br />
<strong>在函数中使用界限通配符</strong><br />
在之前的章节中，你学会了通过传递不同的类型变量s来创建不同JAVA类型的泛型，但并不考虑类型变量s之间的继承关系。在很多情况下，你想一个函数有不同的List参数。比如，你有一个函数getAverage，他返回了一个List中成员的平均值。然而，如果你把List&lt;Number&gt;作为getAverage的参数，你就没法传递List&lt;Integer&gt; 或List&lt;Double&gt;参数，因为List&lt;Number&gt;和List&lt;Integer&gt; 和List&lt;Double&gt;不是同样的类型。<br />
<br />
你能使用原型或使用通配符，但这样无法在编译时进行安全类型检查，因为你能传递任何类型的List，比如List&lt;String&gt;的实例。你可以使用List&lt;Number&gt;作为参数，但是你就只能传递List&lt;Number&gt;给函数。但这样就使你的函数功能减少，因为你可能更多的时候要操作List&lt;Integer&gt;或List&lt;Long&gt;，而不是List&lt;Number&gt;。<br />
<br />
J2SE5.0增加了一个规则来解决了这种约束，这个规则就是允许你定义一个上界(upper bound) 类型变量.在这种方式中，你能传递一个类型或它的子类。在上面getAverage函数的例子中，你能传递一个List&lt;Number&gt;或它的子类的实例，比如List&lt;Integer&gt; or List&lt;Float&gt;。<br />
<br />
使用上界规则的语法这么定义的：GenericType&lt;? extends upperBoundType&gt;. 比如，对getAverage函数的参数，你可以这么写List&lt;? extends Number&gt;. 下面例子说明了如何使用这种规则。<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
import java.util.ArrayList;<br />
import java.util.List;<br />
public class BoundedWildcardTest {<br />
&nbsp;&nbsp;public static double getAverage(List&lt;? extends Number&gt; numberList)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;double total = 0.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (Number number : numberList)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total += number.doubleValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;return total/numberList.size();<br />
&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Integer&gt; integerList = new ArrayList&lt;Integer&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;integerList.add(3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;integerList.add(30);<br />
&nbsp;&nbsp;&nbsp;&nbsp;integerList.add(300);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(getAverage(integerList)); // 111.0<br />
&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Double&gt; doubleList = new ArrayList&lt;Double&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;doubleList.add(3.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;doubleList.add(33.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(getAverage(doubleList)); // 18.0<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
由于有了上界规则，上面例子中的getAverage函数允许你传递一个List&lt;Number&gt; 或一个类型变量是任何java.lang.Number子类的List。<br />
<br />
<strong>下界规则</strong><br />
关键字extends定义了一个类型变量的上界。通过使用super关键字，我们可以定义一个类型变量的下界，尽管使用的情况不多。比如，如果一个函数的参数是List&lt;? super Integer&gt;，那么意味着你可以传递一个List&lt;Integer&gt;的实例或者任何java.lang.Integer的超类(superclass)。<br />
<br />
<strong>创建泛型</strong><br />
<br />
前面的章节主要说明了如何使使用泛型，特别是集合框架中的类。现在我们开始学习如何写自己的泛型。<br />
<br />
基本上，除了声明一些你想要使用的类型变量s外，一个泛型和别的类没有什么区别。这些类型变量s位于类型后面的&lt;&gt;中。比如，下面的Point就是个泛型。一个Point对象代表了一个系统中的点，它有横坐标和纵坐标。通过使Point泛型化，你能定义一个点实例的精确程度。比如，如果一个Point对象需要非常精确，你就把Double作为类型变量。否则，Integer 就够了。<br />
<pre class="overflow" title="pre code">package com.brainysoftware.jdk5.app16;<br />
public class Point&lt;T&gt; {<br />
&nbsp;&nbsp;T x;<br />
&nbsp;&nbsp;T y;<br />
&nbsp;&nbsp;public Point(T x, T y) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.x = x;<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.y = y;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public T getX() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return x;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public T getY() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return y;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public void setX(T x) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.x = x;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public void setY(T y) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;this.y = y;<br />
&nbsp;&nbsp;}<br />
}</pre>
<br />
<br />
在这个例子中，T是Point的类型变量 。T是getX和getY的返回值类型，也是setX和setY的参数类型。此外，构造函数结合两个T参数。<br />
使用point类就像使用别的类一样。比如，下面的例子创建了两个Point对象：ponint1和point2。前者把Integer作为类型变量，而后者把Double作为类型变量。<br />
<br />
<pre class="overflow" title="pre code">Point&lt;Integer&gt; point1 = new Point&lt;Integer&gt;(4, 2);<br />
point1.setX(7);<br />
Point&lt;Double&gt; point2 = new Point&lt;Double&gt;(1.3, 2.6);<br />
point2.setX(109.91);</pre>
<br />
<br />
<strong>总结</strong><br />
泛型使代码在编译时有了更严格的类型检查。特别是在集合框架中，泛型有两个作用。第一，他们增加了对集合类型在编译时的类型检查，所以集合类所能持有的类型对传递给它的参数类型起了限制作用。比如你创建了一个持有strings的java.util.List实例，那么他就将不能接受Integers或别的类型。其次，当你从一个集合中取得一个元素时，泛型消除了类型转换的必要。<br />
泛型能够在没有类型变量的情况下使用，比如，作为原型。这些措施让Java 5之前的代码能够运行在JRE 5中。但是，对新的应用程序，你最好不要使用原型，因为以后Java可能不支持他们。<br />
<br />
你已经知道通过传递不同类型的类型变量给泛型可以产生不同的JAVA类型。就是说List&lt;String&gt;和List&lt;Object&gt;的类型是不同的。尽管String是java.lang.Object。但是传递一个List&lt;String&gt;给一个参数是List&lt;Object&gt;的函数会参数会产生编译错误（compile error）。函数能用 ? 通配符使其接受任何类型的参数。List&lt;?&gt; 意味着任何类型的对象。<br />
最后，你已经看到了写一个泛型和别的一般JAVA类没有什么区别。你只需要在类型名称后面的&lt;&gt;中声明一系列的类型变量s就行了。这些类型变量s就是返回值类型或者参数类型。根据惯例，一个类型变量用一个大写字母表示。<br />
<img src ="http://www.blogjava.net/jelver/aggbug/180746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-02-19 22:08 <a href="http://www.blogjava.net/jelver/articles/180746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>递归实现类似腾讯的积分等级处理 (原创)</title><link>http://www.blogjava.net/jelver/articles/175567.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Tue, 15 Jan 2008 15:40:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/175567.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/175567.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/175567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/175567.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/175567.html</trackback:ping><description><![CDATA[由于最近做积分系统刚好需要一个类似腾讯qq等级的方式:比如一个太阳等级A表示1000分,一个月亮B表示800分,另外一个星星C表示100分;则若用户的积分为2950则是AABC表示即可,若用户积分为1950则用ABC即可,若用户积分为2150则用AAC即可,若用户积分为1150则用AC即可,以此类推,可以用递归来解决这类问题,代码如下 <br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.ArrayList;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.util.List;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_79_1593_Open_Image" onclick="this.style.display='none'; Codehighlighter1_79_1593_Open_Text.style.display='none'; Codehighlighter1_79_1593_Closed_Image.style.display='inline'; Codehighlighter1_79_1593_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_79_1593_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_79_1593_Closed_Text.style.display='none'; Codehighlighter1_79_1593_Open_Image.style.display='inline'; Codehighlighter1_79_1593_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;BeanShellDemo&nbsp;</span><span id="Codehighlighter1_79_1593_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_79_1593_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;StringBuffer&nbsp;sb&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;StringBuffer();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_130_256_Open_Image" onclick="this.style.display='none'; Codehighlighter1_130_256_Open_Text.style.display='none'; Codehighlighter1_130_256_Closed_Image.style.display='inline'; Codehighlighter1_130_256_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_130_256_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_130_256_Closed_Text.style.display='none'; Codehighlighter1_130_256_Open_Image.style.display='inline'; Codehighlighter1_130_256_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_130_256_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">/**&nbsp;*/</span><span id="Codehighlighter1_130_256_Open_Text"><span style="color: #008000">/**</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;point表示用户的总积分,levellist表示积分等级列表;&lt;br&gt;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;在本例子中需要说明的是积分等级列表是要按顺序的<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;point<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;leverlist<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@return</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span></span><span style="color: #000000"><br />
<img id="Codehighlighter1_317_1194_Open_Image" onclick="this.style.display='none'; Codehighlighter1_317_1194_Open_Text.style.display='none'; Codehighlighter1_317_1194_Closed_Image.style.display='inline'; Codehighlighter1_317_1194_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_317_1194_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_317_1194_Closed_Text.style.display='none'; Codehighlighter1_317_1194_Open_Image.style.display='inline'; Codehighlighter1_317_1194_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;String&nbsp;getMyLand(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;point,&nbsp;List&nbsp;levellist)&nbsp;</span><span id="Codehighlighter1_317_1194_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_317_1194_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;starnum&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;leftpoint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;maxlevel&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Integer.parseInt(levellist.get(levellist.size()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.toString());</span><span style="color: #008000">//</span><span style="color: #008000">列表中的最大等级</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;minlevel&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Integer.parseInt(levellist.get(</span><span style="color: #000000">0</span><span style="color: #000000">).toString());</span><span style="color: #008000">//</span><span style="color: #008000">列表中的最小等级</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000"><br />
<img id="Codehighlighter1_578_623_Open_Image" onclick="this.style.display='none'; Codehighlighter1_578_623_Open_Text.style.display='none'; Codehighlighter1_578_623_Closed_Image.style.display='inline'; Codehighlighter1_578_623_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_578_623_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_578_623_Closed_Text.style.display='none'; Codehighlighter1_578_623_Open_Image.style.display='inline'; Codehighlighter1_578_623_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(levellist.size()&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;point</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;minlevel)</span><span id="Codehighlighter1_578_623_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_578_623_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">积分不够最小等级,则默认为最低的等级</span><span style="color: #000000">"</span><span style="color: #000000">+</span><span style="color: #000000">minlevel;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #0000ff">else</span><span style="color: #000000"><br />
<img id="Codehighlighter1_678_1166_Open_Image" onclick="this.style.display='none'; Codehighlighter1_678_1166_Open_Text.style.display='none'; Codehighlighter1_678_1166_Closed_Image.style.display='inline'; Codehighlighter1_678_1166_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_678_1166_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_678_1166_Closed_Text.style.display='none'; Codehighlighter1_678_1166_Open_Image.style.display='inline'; Codehighlighter1_678_1166_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(levellist.size()&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;point&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;minlevel)&nbsp;</span><span id="Codehighlighter1_678_1166_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_678_1166_Open_Text"><span style="color: #000000">{&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">当用户积分小于最小等级值则不做处理</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000"><br />
<img id="Codehighlighter1_753_919_Open_Image" onclick="this.style.display='none'; Codehighlighter1_753_919_Open_Text.style.display='none'; Codehighlighter1_753_919_Closed_Image.style.display='inline'; Codehighlighter1_753_919_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_753_919_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_753_919_Closed_Text.style.display='none'; Codehighlighter1_753_919_Open_Image.style.display='inline'; Codehighlighter1_753_919_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(point&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;maxlevel&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;levellist.size()&nbsp;</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_753_919_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_753_919_Open_Text"><span style="color: #000000">{&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;小于最大等级则</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;levellist.remove(levellist.size()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;将当前list中的最大等级移除&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leftpoint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;point;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">(注意因为例子中的list是由小到大排序的,乱顺则要另外处理)</span><span style="color: #008000"><br />
<img id="Codehighlighter1_926_1126_Open_Image" onclick="this.style.display='none'; Codehighlighter1_926_1126_Open_Text.style.display='none'; Codehighlighter1_926_1126_Closed_Image.style.display='inline'; Codehighlighter1_926_1126_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_926_1126_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_926_1126_Closed_Text.style.display='none'; Codehighlighter1_926_1126_Open_Image.style.display='inline'; Codehighlighter1_926_1126_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_926_1126_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_926_1126_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;starnum&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;point&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;maxlevel;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">取商&nbsp;比如280/6&nbsp;=&nbsp;46</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;leftpoint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;point&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">&nbsp;maxlevel;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">取模&nbsp;比如280%6&nbsp;=&nbsp;4</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.append(</span><span style="color: #000000">"</span><span style="color: #000000">有</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;starnum&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">个等级为</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;maxlevel&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">的头衔</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">#</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getMyLand(leftpoint,&nbsp;levellist);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;sb.toString();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1237_1591_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1237_1591_Open_Text.style.display='none'; Codehighlighter1_1237_1591_Closed_Image.style.display='inline'; Codehighlighter1_1237_1591_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1237_1591_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1237_1591_Closed_Text.style.display='none'; Codehighlighter1_1237_1591_Open_Image.style.display='inline'; Codehighlighter1_1237_1591_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id="Codehighlighter1_1237_1591_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1237_1591_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_1261_1287_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1261_1287_Open_Text.style.display='none'; Codehighlighter1_1261_1287_Closed_Image.style.display='inline'; Codehighlighter1_1261_1287_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1261_1287_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1261_1287_Closed_Text.style.display='none'; Codehighlighter1_1261_1287_Open_Image.style.display='inline'; Codehighlighter1_1261_1287_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;leverarray[]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1261_1287_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1261_1287_Open_Text"><span style="color: #000000">{&nbsp;</span><span style="color: #000000">50</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">100</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">300</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">500</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">1000</span><span style="color: #000000">&nbsp;}</span></span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;levellist&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ArrayList</span><span style="color: #000000">&lt;</span><span style="color: #000000">Integer</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />
<img id="Codehighlighter1_1390_1427_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1390_1427_Open_Text.style.display='none'; Codehighlighter1_1390_1427_Closed_Image.style.display='inline'; Codehighlighter1_1390_1427_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1390_1427_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1390_1427_Closed_Text.style.display='none'; Codehighlighter1_1390_1427_Open_Image.style.display='inline'; Codehighlighter1_1390_1427_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;leverarray.length;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1390_1427_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1390_1427_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;levellist.add(leverarray[i]);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;userpoint&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">20</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;userpoint2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2190</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(getMyLand(userpoint,&nbsp;levellist));<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(getMyLand(userpoint2,&nbsp;levellist));<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<br />
<br />
执行结果如:<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">积分不够最小等级,则默认为最低的等级50<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />有2个等级为1000的头衔#有1个等级为100的头衔#有1个等级为50的头衔#</span></div>
<br />
通过其他方法对返回的串做处理即可,有好方法的朋友欢迎沟通!!<br />
<img src ="http://www.blogjava.net/jelver/aggbug/175567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2008-01-15 23:40 <a href="http://www.blogjava.net/jelver/articles/175567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中的io系统总结（转）</title><link>http://www.blogjava.net/jelver/articles/170604.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Wed, 26 Dec 2007 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/170604.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/170604.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/170604.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/170604.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/170604.html</trackback:ping><description><![CDATA[<p>java中的io中的（input/output）stream无非就是包括基于字符的stream、基于字节的stream和把字节导向的stream转换<br />
字符为导向的stream的stream。（很难理解么？）<br />
以字节为导向的stream------InputStream/OutputStream<br />
InputStream 和 OutputStream是两个abstact类，对于字节为导向的stream都扩展这两个鸡肋（基类^_^）;<br />
--InputStream<br />
ByteArrayInputStream -- 把内存中的一个缓冲区作为InputStream使用.</p>
<p>construct---ByteArrayInputStream(byte[])创建一个新字节数组输入流，它从指定字节数组中读取数据。<br />
---ByteArrayInputStream(byte[], int, int) 创建一个新字节数组输入流，它从指定字节数组中读取数据。<br />
---mark::该字节数组未被复制。</p>
<p>StringBufferInputStream -- 把一个String对象作为InputStream .<br />
注释：不推荐使用 StringBufferInputStream 方法。 此类不能将字符正确的转换为字节。<br />
同 JDK 1.1 版中的类似，从一个串创建一个流的最佳方法是采用 StringReader 类。 </p>
<p>construct---StringBufferInputStream(String) 据指定串创建一个读取数据的输入流串。</p>
<p>FileInputStream -- 把一个文件作为InputStream，实现对文件的读取操作 </p>
<p>construct---FileInputStream(File) 创建一个输入文件流，从指定的 File 对象读取数据。<br />
---FileInputStream(FileDescriptor) 创建一个输入文件流，从指定的文件描述器读取数据。<br />
---FileInputStream(String) 创建一个输入文件流，从指定名称的文件读取数据。</p>
<p>method ---- read() 从当前输入流中读取一字节数据。 <br />
read(byte[]) 将当前输入流中 b.length 个字节数据读到一个字节数组中。 <br />
read(byte[], int, int) 将输入流中 len 个字节数据读入一个字节数组中。</p>
<p>PipedInputStream：实现了pipe的概念，主要在线程中使用. 管道输入流是指一个通讯管道的接收端。<br />
一个线程通过管道输出流发送数据，而另一个线程通过管道输入流读取数据，<br />
这样可实现两个线程间的通讯。</p>
<p>PipedInputStream() 创建一个管道输入流，它还未与一个管道输出流连接。 <br />
PipedInputStream(PipedOutputStream) 创建一个管道输入流, 它已连接到一个管道输出流。 </p>
<p>SequenceInputStream：把多个InputStream合并为一个InputStream .&#8220;序列输入流&#8221;类允许应用程序把几个输入流连续地合并起来，<br />
并且使它们像单个输入流一样出现。每个输入流依次被读取，直到到达该流的末尾。<br />
然后&#8220;序列输入流&#8221;类关闭这个流并自动地切换到下一个输入流。 <br />
SequenceInputStream(Enumeration) 创建一个新的序列输入流，并用指定的输入流的枚举值初始化它。 <br />
SequenceInputStream(InputStream, InputStream) 创建一个新的序列输入流，初始化为首先 读输入流 s1, 然后读输入流 s2。</p>
<p>--OutputSteam</p>
<p>ByteArrayOutputStream：把信息存入内存中的一个缓冲区中.该类实现一个以字节数组形式写入数据的输出流。<br />
当数据写入缓冲区时，它自动扩大。用 toByteArray() 和 toString() 能检索数据。 </p>
<p>construct --- ByteArrayOutputStream() 创建一个新的字节数组输出流。<br />
--- ByteArrayOutputStream() 创建一个新的字节数组输出流。 <br />
--- ByteArrayOutputStream(int) 创建一个新的字节数组输出流，并带有指定大小字节的缓冲区容量。 <br />
toString(String) 根据指定字符编码将缓冲区内容转换为字符串，并将字节转换为字符。 <br />
write(byte[], int, int) 将指定字节数组中从偏移量 off 开始的 len 个字节写入该字节数组输出流。 <br />
write(int) 将指定字节写入该字节数组输出流。 <br />
writeTo(OutputStream) 用 out.write(buf, 0, count) 调用输出流的写方法将该字节数组输出流的全部内容写入指定的输出流参数。 </p>
<p>FileOutputStream:文件输出流是向 File 或 FileDescriptor 输出数据的一个输出流。</p>
<p>FileOutputStream(File) 创建一个文件输出流，向指定的 File 对象输出数据。 <br />
FileOutputStream(FileDescriptor) 创建一个文件输出流，向指定的文件描述器输出数据。 <br />
FileOutputStream(String) 创建一个文件输出流，向指定名称的文件输出数据。 <br />
FileOutputStream(String, boolean) 用指定系统的文件名，创建一个输出文件。</p>
<p>PipedOutputStream:管道输出流是指一个通讯管道的发送端。 一个线程通过管道输出流发送数据，<br />
而另一个线程通过管道输入流读取数据，这样可实现两个线程间的通讯。</p>
<p>PipedOutputStream() 创建一个管道输出流，它还未与一个管道输入流连接。 <br />
PipedOutputStream(PipedInputStream) 创建一个管道输出流，它已连接到一个管道输入流。</p>
<p><br />
以字符为导向的stream Reader/Writer</p>
<p>以Unicode字符为导向的stream，表示以Unicode字符为单位从stream中读取或往stream 中写入信息。<br />
Reader/Writer 为abstact类<br />
以Unicode字符为导向的stream包括下面几种类型： </p>
<p>－－ Reader</p>
<p>1) CharArrayReader：与ByteArrayInputStream对应 <br />
CharArrayReader(char[]) 用指定字符数组创建一个 CharArrayReader。<br />
CharArrayReader(char[], int, int) 用指定字符数组创建一个 CharArrayReader。</p>
<p>2) StringReader：与StringBufferInputStream对应 <br />
StringReader(String) 创建一新的串读取者。<br />
3) FileReader：与FileInputStream对应 </p>
<p>4) PipedReader：与PipedInputStream对应 </p>
<p>－－ Writer</p>
<p>1) CharArrayWrite：与ByteArrayOutputStream对应 <br />
2) StringWrite：无与之对应的以字节为导向的stream <br />
3) FileWrite：与FileOutputStream对应 <br />
4) PipedWrite：与PipedOutputStream对应 </p>
<p>两种不现导向的stream之间的转换<br />
InputStreamReader和OutputStreamReader：把一个以字节为导向的stream转换成一个以字符为导向的stream。<br />
一个 InputStreamReader 类是从字节流到字符流的桥梁：它读入字节，并根据指定的编码方式，将之转换为字符流。<br />
使用的编码方式可能由名称指定，或平台可接受的缺省编码方式。</p>
<p>InputStreamReader 的 read() 方法之一的每次调用，可能促使从基本字节输入流中读取一个或多个字节。<br />
为了达到更高效率，考虑用 BufferedReader 封装 InputStreamReader，<br />
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));</p>
<p>InputStreamReader(InputStream) 用缺省的字符编码方式，创建一个 InputStreamReader。 <br />
InputStreamReader(InputStream, String) 用已命名的字符编码方式，创建一个 InputStreamReader。</p>
<p>OutputStreamWriter 将多个字符写入到一个输出流，根据指定的字符编码将多个字符转换为字节。 <br />
每个 OutputStreamWriter 合并它自己的 CharToByteConverter, 因而是从字符流到字节流的桥梁。</p>
<p>FilterInputStream、RandomAccessFile 见例子。<br />
ObjectInputStream 、 ObjectOutputStream见另外blog。</p>
<p><br />
Java IO的一般使用原则：</p>
<p>一、按数据来源（去向）分类：<br />
1、是文件： FileInputStream, FileOutputStream, FileReader, FileWriter<br />
2、是byte[]：ByteArrayInputStream, ByteArrayOutputStream<br />
3、是Char[]: CharArrayReader, CharArrayWriter<br />
4、是String: StringBufferInputStream, StringReader, StringWriter<br />
5、网络数据流：InputStream, OutputStream, Reader, Writer</p>
<p>二、按是否格式化输出分：<br />
1、要格式化输出：PrintStream, PrintWriter</p>
<p>三、按是否要缓冲分：<br />
1、要缓冲：BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter</p>
<p>四、按数据格式分：<br />
1、二进制格式（只要不能确定是纯文本的）: InputStream, OutputStream及其所有带Stream结束的子类<br />
2、纯文本格式（含纯英文与汉字或其他编码方式）；Reader, Writer及其所有带Reader, Writer的子类</p>
<p>五、按输入输出分：<br />
1、输入：Reader, InputStream类型的子类<br />
2、输出：Writer, OutputStream类型的子类</p>
<p>六、特殊需要：<br />
1、从Stream到Reader,Writer的转换类：InputStreamReader, OutputStreamWriter<br />
2、对象输入输出：ObjectInputStream, ObjectOutputStream<br />
3、进程间通信：PipeInputStream, PipeOutputStream, PipeReader, PipeWriter<br />
4、合并输入：SequenceInputStream<br />
5、更特殊的需要：PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader</p>
<p>决定使用哪个类以及它的构造进程的一般准则如下（不考虑特殊需要）：<br />
首先，考虑最原始的数据格式是什么： 原则四<br />
第二，是输入还是输出：原则五<br />
第三，是否需要转换流：原则六第1点<br />
第四，数据来源（去向）是什么：原则一<br />
第五，是否要缓冲：原则三 （特别注明：一定要注意的是readLine()是否有定义，有什么比read, write更特殊的输入或输出方法）<br />
第六，是否要格式化输出：原则二<br />
<br />
<br />
文章2：<br />
首先是java的IO。这破东西可真费事，<span class="original_words">I/O</span>类库常使用&#8221;流(<span class="original_words">stream</span>)&#8221;这种抽象。所谓&#8221;流&#8221;是一种能生成或接受数据的，代表数据的源和目标的对象。流把<span class="original_words">I/O</span>设备内部的具体操作给隐藏起来了。 正如<span class="original_words">JDK</span>文档所显示的，<span class="original_words">Java</span>的<span class="original_words">I/O</span>类库分成输入和输出两大部分。所有<span class="original_words">InputStream</span>和<span class="original_words">Reader</span>的派生类都有一个基本的，继承下来的，能读取单个或<span class="original_words">byte</span>数组的<span class="original_words">read( )</span>方法。同理，所有<span class="original_words">OutputStream</span>和<span class="original_words">Writer</span>的派生类都有一个基本的，能写入单个或<span class="original_words">byte</span>数组的<span class="original_words">write( )</span>方法。但通常情况下，你是不会去用这些方法的；它们是给其它类用的 —— 而后者会提供一些更实用的接口。因此，你很少会碰到只用一个类就能创建一个流的情形，实际上你得把多个对象叠起来，并以此来获取所需的功能。<span class="original_words">Java</span>的流类库之所以会那么让人犯晕，最主要的原因就是&#8221;你必须为创建一个流而动用多个对象&#8221;。<a id="more-131"></a><br />
<strong>Java的IO类结构：<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根接口是InputStream/OutputStream，充当数据源的IO类有FileInputStream/FileOutputStream，ByteArrayInputStream&nbsp; / ByteArrayOutputStream&nbsp; 等，充当装饰功能的IO类有BufferedInputStream&nbsp; /&nbsp;&nbsp; BufferedOutputStream，DataInputStream&nbsp;&nbsp; /&nbsp;&nbsp; DataOutputStream等，<br />
&nbsp;&nbsp; 它们都是继承装饰接口FilterInputStream/FilterOutputStream。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用IO时，首先创建一个数据源IO，然后根据需要的功能创建装饰类IO，其构造函数的参数为已创建的数据源IO。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们以创建一个具有缓冲的文件输入流为例，假定需要从磁盘读取文件&#8220;C:\log.txt&#8221;：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个FileInputStream:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileInputStream fileInput = new FileInputStream(&#8221;C:\\log.txt&#8221;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个BufferedInputStream:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BufferedInputStream bufferedInput = new BufferedInputStream(fileInput);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 现在得到的bufferedInput即是具有缓冲的文件输入流<br />
　　或者进一步简写如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp; InputStream input = new BufferedInputStream(new FileInputStream(&#8221;C:\\log.txt&#8221;));<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 现在得到的input即是具有缓冲的文件输入流<br />
<strong>java.io.Reader 和 java.io.InputStream 区别<br />
</strong>　　java.io.Reader 和 java.io.InputStream 组成了 Java 输入类。Reader 用于读入16位字符，也就是 Unicode 编码的字符；而 InputStream 用于读入 ASCII 字符和二进制数据。<br />
在 Java 中，有不同类型的 Reader 输入流对应于不同的数据源：<br />
&nbsp;&nbsp;&nbsp; FileReader 用于从文件输入；<br />
&nbsp;&nbsp;&nbsp; CharArrayReader 用于从程序中的字符数组输入；<br />
&nbsp;&nbsp;&nbsp; StringReader 用于从程序中的字符串输入；<br />
&nbsp;&nbsp;&nbsp; PipedReader 用于读取从另一个线程中的 PipedWriter 写入管道的数据。<br />
相应的也有不同类型的 InputStream 输入流对应于不同的数据源：FileInputStream，ByteArrayInputStream，StringBufferInputStream，PipedInputStream。另外，还有两种没有对应 Reader 类型的 InputStream 输入流：<br />
&nbsp;&nbsp;&nbsp; Socket 用于套接字；<br />
&nbsp;&nbsp;&nbsp; URLConnection 用于 URL 连接。<br />
这两个类使用 getInputStream() 来读取数据。<br />
相应的，java.io.Writer 和 java.io.OutputStream 也有类似的区别。<br />
1、Java技术支持两种数据类型的流<br />
InputStream和OutputStream：字节流。其它字节流都是InputStream或OutputStream的子类。<br />
Reader和 Writer：字符流。其它字符流都是Reader或Writer的子类。<br />
2、节点流<br />
Java 2 SDK中有三种基本类型的节点：文件(file)、内存(memory)、管道(pipe)。<br />
3、过程流<br />
过程流在其它流之上，完成排序、变换等操作。过程流也被称做过滤流。<br />
当你需要改变输入流的原始数据时，你可以将一个过滤输入流连接到一个原始的输入流上。<br />
用过滤流将原始数据变换成你需要的格式。&nbsp;&nbsp;<br />
4、基本字节流类<br />
4.1、FileInputStream和FileOutputStream<br />
这两个节点流用来操纵磁盘文件。这些类的构造函数允许你指定它们所连接的文件。<br />
要构造一个FileInputStream，所关联的文件必须存在而且是可读的。<br />
如果你要构造一个FileOutputStream而输出文件已经存在，则它将被覆盖。<br />
FileInputStream infile = new FileInputStream(&#8221;myfile.dat&#8221;);<br />
FileOutputStream outfile = new FileOutputStream(&#8221;results.dat&#8221;);<br />
4.1、 BufferInputStream和BufferOutputStream<br />
这些是过滤器流，它们可以提高I/O操作的效率。<br />
4.3、 PipedInputStream和PipedOutputStream<br />
管道流用来在线程间进行通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。<br />
要使管道流有用，必须有一个输入方和一个输出方。<br />
4.4、 DataInputStream和DataOutputStream<br />
这些过滤器通过流来读写Java基本类<br />
5、 基本字符流类<br />
图阐述了Reader和Writer字符流的体系结构。<br />
5.1、InputStreamReader 和 OutputStreamWriter<br />
用于字节流与字符流之间的转换接口。<br />
当你构造一个InputStreamReader或OutputStreamWriter时，转换规则定义了16位Unicode和其它平台的特定表示之间的转换。<br />
InputStreamReader从一个数据源读取字节，并自动将其转换成Unicode字符。<br />
如果你特别声明，InputStreamReade会将字节流转换成其它种类的字符流。<br />
OutputStreamWriter将字符的Unicode编码写到输出流，如果你的使用的不是Unicode字符，OutputStreamWriter会将你的字符编码转换成Unicode编码。<br />
5.2.、缓冲读者和作者<br />
因为在各种格式之间进行转换和其它I/O操作很类似，所以在处理大块数据时效率最高。<br />
在InputStreamReader和OutputStreamWriter的结尾链接一个BufferedReader和BufferedWriter是一个好主意。<br />
记住对BufferedWriter使用flush()方法。<br />
5.3、 使用其它字符转换<br />
如果你需要从一个非本地(例如，从连接到一个不同类型的机器的网络连接读取)的字符编码读取输入，<br />
你可以象下面这个程序那样，使用显式的字符编码构造ir=new InputStreamReader(System.in,&nbsp; &#8220;8859_1&#8243;);<br />
注：如果你通过网络连接读取字符，就应该使用这种形式。<br />
否则，你的程序会总是试图将所读取的字符当作本地表示来进行转换，而这并不总是正确的。ISO 8859-1是映射到ASCII的Latin-1编码模式。<br />
6、 对象串行化<br />
java.io.Serializable接口支持将一个Java技术对象存放到一个流中。<br />
将一个对象存放到某种类型的永久存储器上称为&#8221;保持&#8221;。<br />
如果一个对象可以被存放到磁盘或磁带上，或者可以发送到另外一台机器并存放到存储器或磁盘上，那么这个对象就被称为可保持的。<br />
java.io.Serializable接口没有任何方法，它只作为一个&#8221;标记&#8221;，用来表明实现了这个接口的类可以串行化。<br />
类中没有实现Serializable接口的对象不能被保持。<br />
// 文件实现追加：<br />
// 其中的FileWriter()中的第二个参数的含义是:是否在文件中追加内容<br />
PrintWriter out = new PrintWriter(new FileWriter(logFileName, true), true);<br />
Java读写文件最常用的类是FileInputStream/FileOutputStream和FileReader/FileWriter。<br />
其中FileInputStream和FileOutputStream是基于字节流的，常用于读写二进制文件。<br />
读写字符文件建议使用基于字符的FileReader和FileWriter，省去了字节与字符之间的转换。<br />
但这两个类的构造函数默认使用系统的编码方式，如果文件内容与系统编码方式不一致，可能会出现乱码。<br />
在这种情况下，建议使用FileReader和FileWriter的父类：InputStreamReader/OutputStreamWriter，<br />
它们也是基于字符的，但在构造函数中可以指定编码类型：InputStreamReader(InputStream in, Charset cs) 和OutputStreamWriter(OutputStream out, Charset cs)。&nbsp; </p>
<p>// 读写文件的编码：<br />
InputStreamReader r = new InputStreamReader(new FileInputStream(fileName), &#8220;utf-8&#8243;);<br />
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName),&#8221;utf-8&#8243;);</p>
<p>/**<br />
三种IO性能比较:<br />
在读写一个10k文件的时候，三种方式的耗时如下:<br />
InputStreamReader And OutputStreamWriter : 63ms (可以设置文件的编码，如果不用buffer)<br />
BufferedReader And BufferedWriter : 31ms&nbsp;<br />
BufferedInputStream And BufferedOutputStream : 16ms<br />
*/</p>
<p>/**<br />
*&nbsp;Description: Test the java IO&#8217;s efficiency<br />
*&nbsp;Author: KevinChen<br />
*&nbsp;Date: 2007-02-18<br />
*/<br />
import java.io.*;</p>
<p>/**<br />
*&nbsp;using the InputStreamReader And OutputStreamWriter<br />
*/<br />
class EncoderRW {<br />
&nbsp;public static String read(String fileName) throws IOException {<br />
&nbsp;&nbsp;StringBuffer sb = new StringBuffer();<br />
&nbsp; /*此处读文件时用了buffer，如果不用，性能损失一倍*/<br />
&nbsp;&nbsp;BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), &#8220;utf-8&#8243;));<br />
&nbsp;&nbsp;String s;<br />
&nbsp;&nbsp;while((s = in.readLine()) != null) {<br />
&nbsp;&nbsp;&nbsp; sb.append(s);<br />
&nbsp;&nbsp;&nbsp; sb.append(&#8221;\n&#8221;);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;in.close();<br />
&nbsp;&nbsp;return sb.toString();<br />
&nbsp;}<br />
&nbsp;public void write(String fileName, String text) throws IOException {<br />
&nbsp;&nbsp;OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName),&#8221;utf-8&#8243;);<br />
&nbsp;&nbsp;out.write(text);<br />
&nbsp;&nbsp;out.flush();<br />
&nbsp;&nbsp;out.close();<br />
&nbsp;}<br />
}</p>
<p>/**<br />
*&nbsp;using the BufferedReader And BufferedWriter<br />
*/<br />
class WriterReader {<br />
&nbsp;public String read(String fileName) throws IOException {<br />
&nbsp;&nbsp;StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;BufferedReader in = new BufferedReader(new FileReader(fileName));<br />
&nbsp;&nbsp;String s;<br />
&nbsp;&nbsp;while((s = in.readLine()) != null) {<br />
&nbsp;&nbsp;&nbsp; sb.append(s);<br />
&nbsp;&nbsp;&nbsp; sb.append(&#8221;\n&#8221;);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;in.close();<br />
&nbsp;&nbsp;return sb.toString();<br />
&nbsp;}<br />
&nbsp;public void write(String fileName, String text) throws IOException {<br />
&nbsp;&nbsp;PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));<br />
&nbsp;&nbsp;out.print(text);<br />
&nbsp;&nbsp;out.close();<br />
&nbsp;}<br />
}</p>
<p>/**<br />
*&nbsp;using the BufferedInputStream And BufferedOutputStream<br />
*/<br />
class BufferedStream{<br />
&nbsp;public byte[] read(String fileName) throws IOException {<br />
&nbsp;&nbsp;BufferedInputStream remoteBIS = new BufferedInputStream(new FileInputStream(fileName));<br />
&nbsp;&nbsp;ByteArrayOutputStream baos = new ByteArrayOutputStream(10240);<br />
&nbsp;&nbsp;byte[] buf = new byte[1024];<br />
&nbsp;&nbsp;int bytesRead = 0;<br />
&nbsp;&nbsp;while(bytesRead &gt;= 0)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;baos.write(buf, 0, bytesRead);<br />
&nbsp;&nbsp;&nbsp;bytesRead = remoteBIS.read(buf);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;byte[] content = baos.toByteArray();<br />
&nbsp;&nbsp;return content;<br />
&nbsp;}<br />
&nbsp;public void write(String fileName, byte[] content)&nbsp; throws IOException {<br />
&nbsp;&nbsp;BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName));<br />
&nbsp;&nbsp;out.write(content);<br />
&nbsp;&nbsp;out.flush();<br />
&nbsp;&nbsp;out.close();<br />
&nbsp;}<br />
}</p>
<p>public class TestIO<br />
{<br />
&nbsp;public static void main(String[] args)throws IOException {<br />
&nbsp;&nbsp;long currentTime = System.currentTimeMillis() ;<br />
&nbsp;&nbsp;EncoderRW rw = new EncoderRW();<br />
&nbsp;&nbsp;rw.write(&#8221;index.dat&#8221;,rw.read(&#8221;FileUtil.java&#8221;));<br />
&nbsp;&nbsp;System.out.println(&#8221;cost time:&#8221; + Long.toString(System.currentTimeMillis()-currentTime) + &#8221; ms&#8221;);</p>
<p>&nbsp;&nbsp;currentTime = System.currentTimeMillis() ;<br />
&nbsp;&nbsp;WriterReader wr = new WriterReader();<br />
&nbsp;&nbsp;wr.write(&#8221;index.dat&#8221;,wr.read(&#8221;FileUtil.java&#8221;));<br />
&nbsp;&nbsp;System.out.println(&#8221;cost time:&#8221; + Long.toString(System.currentTimeMillis()-currentTime) + &#8221; ms&#8221;);</p>
<p>&nbsp;&nbsp;currentTime = System.currentTimeMillis() ;<br />
&nbsp;&nbsp;BufferedStream bf = new BufferedStream();<br />
&nbsp;&nbsp;bf.write(&#8221;index.dat&#8221;,bf.read(&#8221;FileUtil.java&#8221;));<br />
&nbsp;&nbsp;System.out.println(&#8221;cost time:&#8221; + Long.toString(System.currentTimeMillis()-currentTime) + &#8221; ms&#8221;);<br />
&nbsp;}<br />
}</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/jelver/aggbug/170604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-12-26 15:28 <a href="http://www.blogjava.net/jelver/articles/170604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>心跳包检测不可检测断线 (转)</title><link>http://www.blogjava.net/jelver/articles/166102.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Fri, 07 Dec 2007 09:43:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/166102.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/166102.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/166102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/166102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/166102.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一般是用来判断对方（设备，进程或其它网元）是否正常动行，一般采用定时发送简单的通讯包，如果在指定时间段内未收到对方响应，则判断对方已经当掉。用于检测TCP的异常断开。基本原因是服务器端不能有效的判断客户端是否在线也就是说，服务器无法区分客户端是长时间在空闲，还是已经掉线的情况.所谓的心跳包就是客户端定时发送简单的信息给服务器端告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务端...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/166102.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/166102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-12-07 17:43 <a href="http://www.blogjava.net/jelver/articles/166102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四个有用的过滤器 Filter</title><link>http://www.blogjava.net/jelver/articles/164936.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Mon, 03 Dec 2007 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/164936.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/164936.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/164936.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/164936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/164936.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;一、使浏览器不缓存页面的过滤器&nbsp;import&nbsp;javax.servlet.*;import&nbsp;javax.servlet.http.HttpServletResponse;import&nbsp;java.io.IOException;/**&nbsp;*//**&nbsp;*&nbsp;用于的使&nbsp;Browser&nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/164936.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/164936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-12-03 17:13 <a href="http://www.blogjava.net/jelver/articles/164936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP中与路径相关的常用的几个方法</title><link>http://www.blogjava.net/jelver/articles/164484.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Sat, 01 Dec 2007 04:58:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/164484.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/164484.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/164484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/164484.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/164484.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http:/localhost/123/jsp/test.jsp:&lt;%@ page language="java" pageEncoding="UTF-8"%&gt;&nbsp;&lt;%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %&gt;&lt;%@ taglib uri="http://...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/164484.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/164484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-12-01 12:58 <a href="http://www.blogjava.net/jelver/articles/164484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>正则表达式的作用 </title><link>http://www.blogjava.net/jelver/articles/162600.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Fri, 23 Nov 2007 04:47:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/162600.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/162600.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/162600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/162600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/162600.html</trackback:ping><description><![CDATA[<div class="item-content">
<p>正则表达式的作用 </p>
<p>提供更强大的字符串处理能力，测试字符串内的模式，例如，可以测试<a title="输入法技巧" href="http://www.vipcn.com/InfoList/Catalog_35_1.html" target="_blank">输入</a>字符串，以查看字符串内是否出现电话号码模式或身份证号码模式。即数据验证替换文本可以使用正则表达式来识别文档中的特定文本，完全删除该文本或者用其他文本替换它。 </p>
<p>基于模式匹配从字符串中提取子字符串可以查找文档内或输入域内特定的文本。 </p>
<p>在<a title="Java" href="http://www.vipcn.com/InfoList/Catalog_251_1.html" target="_blank">Java</a>中使用正则表达式 </p>
<p>正则表达式在字符串处理上有着强大的功能，sun在jdk1.4加入了对它的支持，jdk1.4中加入了java.util.regex包提供对正则表达式的支持。而且Java.lang.String类中的replaceAll和split函数也是调用的正则表达式来实现的。 </p>
<p>正则表达式对字符串的操作主要包括： </p>
<p>1.字符串匹配 </p>
<p>2.指定字符串替换 </p>
<p>3.指定字符串查找 </p>
<p>4.字符串分割 </p>
<p>Pattern类 </p>
<p>Pattern类的实例表示以字符串形式指定的正则表达式，其语 法类似于Perl所用的语法。 </p>
<p>用字符串形式指定的正则表达式，必须先编译成Pattern类的 实例。生成的模式用于创建Matcher对象，它根据正则表达式与任 意字符序列进行匹配。多个匹配器可以共享一个模式，因为它是非专属的。 </p>
<p>用compile方法把给定的正则表达式编译成模式，然后用 matcher方法创建一个匹配器，这个匹配器将根据此模式对给定输 入进行匹配。pattern 方法可返回编译这个模式所用的正则表达式。 </p>
<p>Matcher类 </p>
<p>通过调用某个模式的matcher方法，从这个模式生成匹配器。 匹配器创建之后，就可以用它来执行三类不同的匹配操作： </p>
<p>matches方法根据此模式，对整个输入序列进行匹配。 </p>
<p>lookingAt方法根据此模式，从开始处对输入序列进 行匹配。 </p>
<p>find方法扫描输入序列，寻找下一个与模式匹配的地方。 </p>
<p>这些方法都会返回一个表示<a title="成功技巧" href="http://www.vipcn.com/InfoList/Catalog_213_1.html" target="_blank">成功</a>或失败的布尔值。如果匹配成功，通过查询 匹配器的状态，可以获得更多的信息。 </p>
<p>构建正则表达式 </p>
<p>\d 等於 [0-9] 数字 </p>
<p>\D 等於 [^0-9] 非数字 </p>
<p>\s 等於 [ \t\n\x0B\f\r] 空白字符 </p>
<p>\S 等於 [^ \t\n\x0B\f\r] 非空白字符 </p>
<p>\w 等於 [a-zA-Z_0-9] 数字或是英文字 </p>
<p>\W 等於 [^a-zA-Z_0-9] 非数字与英文字 </p>
<p>$ 表示每行的结尾 . 匹配所有字符，包括空格、Tab字符甚至换行符 或 []方括号只允许匹配单个字符 ^ 符号称为否符号。如果用在方括号内，表示不想要匹配的字符。 表示每行的开头 ( ) 形成一组查询 </p>
<p>
<center>
<table style="width: 762px; height: 330px" cellspacing="0" cellpadding="2" align="center" border="1">
    <tbody>
        <tr>
            <td style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre>import java.util.regex.*;
            public class RegexExample
            {
            public static void main(String[] args)
            {
            String str="aaabc efg ABC";
            String regEx="aaafff";
            Pattern p=Pattern.compile(regEx);//编译成模式
            Matcher m=p.matcher(str);//创建一个匹配器
            boolean rs=m.find();
            if(rs)
            {
            System.out.println("include!!!");
            }
            else
            {
            System.out.println("no include!!!");
            }
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p>&nbsp;</p>
<p>如果str中有regEx，那么rs为true，否则为flase。如果想在查找时忽略大小写， 则可以写成Pattern p=Pattern.compile(regEx,Pattern.CASE_INSENSITIVE); 提取 (从本例所给完整路径中提取文件名) </p>
<p>
<center>
<table style="width: 789px; height: 284px" cellspacing="0" cellpadding="2" align="center" border="1">
    <tbody>
        <tr>
            <td style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre>import java.util.regex.*;
            public class RegexExample2
            {
            public static void main(String[] args)
            {
            String regEx=".+\\\\(.+)$";
            String str="c:\\dir1\\dir2\\name.txt";
            Pattern p=Pattern.compile(regEx);
            Matcher m=p.matcher(str);
            boolean rs=m.find();
            for(int i=1;i&lt;=m.groupCount();i++)
            {
            System.out.println(m.group(i)); //括号内匹配内容
            }
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p>&nbsp;</p>
<p>以上的执行结果为name.txt，提取的字符串储存在m.group(i)中，其中i最大值为m.groupCount(); 分割 </p>
<p>
<center>
<table style="width: 825px; height: 237px" cellspacing="0" cellpadding="2" align="center" border="1">
    <tbody>
        <tr>
            <td style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre>import java.util.regex.*;
            public class RegexExample3
            {
            public static void main(String[] args)
            {
            String regEx="::";
            Pattern p=Pattern.compile(regEx);
            String[] r=p.split("xd::abc::cde");
            for(int i=0;i&lt;r.length;i++)
            {
            System.out.println(r[i]);
            }
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p>&nbsp;</p>
<p>执行后，r就是{xd,abc,cde}，其实分割时还有跟简单的方法： </p>
<p>String str="xd::abc::cde"; </p>
<p>String[] r=str.split("::"); </p>
<p>替换（删除） </p>
<p>
<center>
<table style="width: 835px; height: 208px" cellspacing="0" cellpadding="2" align="center" border="1">
    <tbody>
        <tr>
            <td style="font-size: 9pt" bgcolor="#e6e6e6">
            <pre>import java.util.regex.*;
            public class RegexExample1
            {
            public static void main(String[] args)
            {
            String regEx="a+";//表示一个或多个a
            Pattern p=Pattern.compile(regEx);
            Matcher m=p.matcher("aaabbced a ccdeaa");
            String s=m.replaceAll("A");
            System.out.println(s);
            }
            }</pre>
            </td>
        </tr>
    </tbody>
</table>
</center>
<p>&nbsp;</p>
<p>结果为"Abbced A ccdeA" </p>
<p>如果写成空串，既可达到删除的功能，比如： </p>
<p>String s=m.replaceAll(""); </p>
<p>结果为"bbced ccde"</p>
<div class="clear"></div>
</div>
<img src ="http://www.blogjava.net/jelver/aggbug/162600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-11-23 12:47 <a href="http://www.blogjava.net/jelver/articles/162600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HttpClient 学习整理 (转)</title><link>http://www.blogjava.net/jelver/articles/162339.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Thu, 22 Nov 2007 04:37:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/162339.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/162339.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/162339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/162339.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/162339.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: source：http://www.blogjava.net/Alpha/archive/2007/01/22/95216.htmlHttpClient 是我最近想研究的东西，以前想过的一些应用没能有很好的实现，发现这个开源项目之后就有点眉目了，令人头痛的cookie问题还是有办法解决滴。在网上整理了一些东西，写得很好，寄放在这里。HTTP 协议可能是现在 Internet 上使用...&nbsp;&nbsp;<a href='http://www.blogjava.net/jelver/articles/162339.html'>阅读全文</a><img src ="http://www.blogjava.net/jelver/aggbug/162339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-11-22 12:37 <a href="http://www.blogjava.net/jelver/articles/162339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java生成GUID的类（转）</title><link>http://www.blogjava.net/jelver/articles/161297.html</link><dc:creator>都市淘沙者</dc:creator><author>都市淘沙者</author><pubDate>Sat, 17 Nov 2007 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/jelver/articles/161297.html</guid><wfw:comment>http://www.blogjava.net/jelver/comments/161297.html</wfw:comment><comments>http://www.blogjava.net/jelver/articles/161297.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/jelver/comments/commentRss/161297.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jelver/services/trackbacks/161297.html</trackback:ping><description><![CDATA[<p align="justify">&nbsp;</p>
<div class="posttitle"><a title="Permalink to : 使用Java生成GUID的类" href="http://www.iuei.cn/blog/?p=85" rel="bookmark">使用Java生成GUID的类</a></div>
<p>GUID是一个128位长的数字，一般用16进制表示。算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成GUID。从理论上讲，如果一台机器每秒产生10000000个GUID，则可以保证（概率意义上）3240年不重复。</p>
<p class="code">import java.net.*;<br />
import java.util.*;<br />
import java.security.*;public class GuidCreator extends Object {</p>
<p>private String seedingString = &#8220;&#8221;;<br />
private String rawGUID = &#8220;&#8221;;<br />
private boolean bSecure = false;<br />
private static Random myRand;<br />
private static SecureRandom mySecureRand;</p>
<p>private static String s_id;</p>
<p>public static final int BeforeMD5 = 1;<br />
public static final int AfterMD5 = 2;<br />
public static final int FormatString = 3;</p>
<p>static {<br />
mySecureRand = new SecureRandom();<br />
long secureInitializer = mySecureRand.nextLong();<br />
myRand = new Random(secureInitializer);<br />
try {<br />
s_id = InetAddress.getLocalHost().toString();<br />
} catch (UnknownHostException e) {<br />
e.printStackTrace();<br />
}<br />
}</p>
<p>/*<br />
* Default constructor. With no specification of security option,<br />
* this constructor defaults to lower security, high performance.<br />
*/<br />
public GuidCreator() { }</p>
<p>/*<br />
* Constructor with security option. Setting secure true<br />
* enables each random number generated to be cryptographically<br />
* strong. Secure false defaults to the standard Random function seeded<br />
* with a single cryptographically strong random number.<br />
*/<br />
public GuidCreator(boolean secure) {<br />
bSecure = secure;<br />
}</p>
<p>/*<br />
* Method to generate the random GUID<br />
*/<br />
private void getRandomGUID(boolean secure) {<br />
MessageDigest md5 = null;<br />
StringBuffer sbValueBeforeMD5 = new StringBuffer();</p>
<p>try {<br />
md5 = MessageDigest.getInstance(&#8221;MD5&#8243;);<br />
} catch (NoSuchAlgorithmException e) {<br />
System.out.println(&#8221;Error: &#8221; + e);<br />
}</p>
<p>try {<br />
long time = System.currentTimeMillis();<br />
long rand = 0;</p>
<p>if (secure) {<br />
rand = mySecureRand.nextLong();<br />
} else {<br />
rand = myRand.nextLong();<br />
}</p>
<p>// This StringBuffer can be a long as you need; the MD5<br />
// hash will always return 128 bits. You can change<br />
// the seed to include anything you want here.<br />
// You could even stream a file through the MD5 making<br />
// the odds of guessing it at least as great as that<br />
// of guessing the contents of the file!<br />
sbValueBeforeMD5.append(s_id);<br />
sbValueBeforeMD5.append(&#8221;:&#8221;);<br />
sbValueBeforeMD5.append(Long.toString(time));<br />
sbValueBeforeMD5.append(&#8221;:&#8221;);<br />
sbValueBeforeMD5.append(Long.toString(rand));</p>
<p>seedingString = sbValueBeforeMD5.toString();<br />
md5.update(seedingString.getBytes());</p>
<p>byte[] array = md5.digest();<br />
StringBuffer sb = new StringBuffer();<br />
for (int j = 0; j &lt; array.length; ++j) {<br />
int b = array[j] &amp; 0xFF;<br />
if (b &lt; 0&#215;10) sb.append(&#8217;0&#8242;);<br />
sb.append(Integer.toHexString(b));<br />
}</p>
<p>rawGUID = sb.toString();</p>
<p>} catch (Exception e) {<br />
System.out.println(&#8221;Error:&#8221; + e);<br />
}<br />
}</p>
<p>public String createNewGuid(int nFormatType, boolean secure) {<br />
getRandomGUID(secure);<br />
String sGuid = &#8220;&#8221;;<br />
if (BeforeMD5 == nFormatType) {<br />
sGuid = this.seedingString;<br />
} else if (AfterMD5 == nFormatType) {<br />
sGuid = this.rawGUID;<br />
} else {<br />
sGuid = this.toString();<br />
}<br />
return sGuid;<br />
}</p>
<p>public String createNewGuid(int nFormatType) {<br />
return this.createNewGuid(nFormatType, this.bSecure);<br />
}</p>
<p>/*<br />
* Convert to the standard format for GUID<br />
* (Useful for SQL Server UniqueIdentifiers, etc.)<br />
* Example: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6<br />
*/<br />
public String toString() {<br />
String raw = rawGUID.toUpperCase();<br />
StringBuffer sb = new StringBuffer();<br />
sb.append(raw.substring(0, 8));<br />
sb.append(&#8221;-&#8221;);<br />
sb.append(raw.substring(8, 12));<br />
sb.append(&#8221;-&#8221;);<br />
sb.append(raw.substring(12, 16));<br />
sb.append(&#8221;-&#8221;);<br />
sb.append(raw.substring(16, 20));<br />
sb.append(&#8221;-&#8221;);<br />
sb.append(raw.substring(20));</p>
<p>return sb.toString();<br />
}<br />
}</p>
<p>/**<br />
* Use Exceple<br />
* public static void main(String args[]) {<br />
* for (int i=0; i&lt; 100; i++) {<br />
* GuidCreator myGUID = new GuidCreator();<br />
* System.out.println(&#8221;Seeding String=&#8221; + myGUID.getNewGuid(GuidCreator.BeforeMD5));<br />
* System.out.println(&#8221;rawGUID=&#8221; + myGUID.getNewGuid(GuidCreator.AfterMD5));<br />
* System.out.println(&#8221;RandomGUID=&#8221; + myGUID.getNewGuid(GuidCreator.FormatString));<br />
* }<br />
* }<br />
*/</p>
<p>本方源于互联网，但已经过作者自己的修改，更易于使用</p>
<img src ="http://www.blogjava.net/jelver/aggbug/161297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jelver/" target="_blank">都市淘沙者</a> 2007-11-17 23:31 <a href="http://www.blogjava.net/jelver/articles/161297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>