﻿<?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-日出而作兮勤于外，日落而归兮忙于内</title><link>http://www.blogjava.net/cherishchen/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 19:01:27 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 19:01:27 GMT</pubDate><ttl>60</ttl><item><title>Hadoop Basic conception</title><link>http://www.blogjava.net/cherishchen/archive/2011/04/21/348689.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Thu, 21 Apr 2011 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/04/21/348689.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/348689.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/04/21/348689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/348689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/348689.html</trackback:ping><description><![CDATA[<p><font color="#4f81bd"><strong>From <em>Hadoop The Definitive Guide 2nd </em></strong></font></p> <p><font color="#4f81bd"><strong>A MapReduce job</strong> is a unit of work that the client wants to be performed: it consists of the input data, the MapReduce program, and configuration information. <strong>Hadoop runs the job by dividing it into tasks</strong>, <strong>of which there are two types: map tasks and reduce tasks.</strong></font></p> <p><br><font color="#4f81bd">There are two types of nodes that control the job execution process: a jobtracker and a number of tasktrackers. The jobtracker coordinates all the jobs run on the system by<br>scheduling&nbsp; tasks&nbsp; to&nbsp; run&nbsp; on&nbsp; tasktrackers.&nbsp; Tasktrackers&nbsp; run&nbsp; tasks&nbsp; and&nbsp; send&nbsp; progress reports to the jobtracker, which keeps a record of the overall progress of each job. If a<br>task fails, the jobtracker can reschedule it on a different tasktracker.</font></p> <p><font color="#4f81bd">Hadoop split input into small fix-size pieces called input splits, and create one map task for each input split.&nbsp; <strong>Thus processing the splits in parallel.</strong></font></p> <p>&nbsp;</p> <p>Hadoop does its best to run the map task on a node where the input data resides in HDFS. This is called the data locality optimization. To avoid to transfer the blocks across the network to the node running the map task to save bandwidth.</p> <p>&nbsp;</p> <p>Map tasks write their output to the local disk, not to HDFS. </p> <p>&nbsp;</p> <p>Reduce tasks don’t have the advantage of data locality—the input to a single reduce task is normally the output from all mappers. </p> <p><strong>The map task outputs have to be transferred across the network to the node where the reduce task is running</strong>, where they are <strong>merged</strong> and then passed to the user-defined reduce function</p> <p>The output of the reduce is normally stored in HDFS for reliability. Each HDFS block of the reduce output, <strong>the first replica is stored on the local node</strong>, with other replicas being stored on off-rack nodes. Thus, writing the reduce output does consume&nbsp; network&nbsp; bandwidth,&nbsp; but&nbsp; only&nbsp; as&nbsp; much&nbsp; as&nbsp; a&nbsp; normal&nbsp; HDFS&nbsp; write&nbsp; pipeline consumes.</p> <p><a href="http://www.blogjava.net/images/blogjava_net/cherishchen/Windows-Live-Writer/0493f7de954e_8D19/image_2.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/Windows-Live-Writer/0493f7de954e_8D19/image_thumb.png" width="517" height="288"></a></p> <p>The numbers of reduce task can be specified independently.</p> <p><strong>When there are multiple reducers, the map tasks partition their output, each creating one partition for each reduce task.</strong> There can be many keys (and their associated values)<br>in each partition, but the records for any given key are all in a single partition. The partitioning can be controlled by a user-defined partitioning function, but normally the<br>default partitioner—which buckets keys using a hash function—works very well.</p> <p><a href="http://www.blogjava.net/images/blogjava_net/cherishchen/Windows-Live-Writer/0493f7de954e_8D19/image_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/Windows-Live-Writer/0493f7de954e_8D19/image_thumb_1.png" width="510" height="289"></a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/348689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-04-21 11:14 <a href="http://www.blogjava.net/cherishchen/archive/2011/04/21/348689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Rounded Border JPanel (JPanel graphics improvements) - CodeProject</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/21/346666.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Mon, 21 Mar 2011 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/21/346666.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/346666.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/21/346666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/346666.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/346666.html</trackback:ping><description><![CDATA[<p>&nbsp;</p> <p><a href="http://www.codeproject.com/KB/java/rounded-jpanel.aspx">Rounded Border JPanel (JPanel graphics improvements) – CodeProject</a></p> <p>&nbsp;</p> <h3>Rounded Border JPanel (JPanel graphics improvements)</h3> <p>By <b><a href="http://www.codeproject.com/script/Membership/View.aspx?mid=5826212">b4rc0ll0</a></b> | 10 Oct 2010  <p><a href="http://www.codeproject.com/info/search.aspx?aidlst=91">Java</a><a href="http://www.codeproject.com/info/search.aspx?aidlst=94">Windows</a><a href="http://www.codeproject.com/info/search.aspx?aidlst=120">Linux</a><a href="http://www.codeproject.com/info/search.aspx?aidlst=148">Design</a><a href="http://www.codeproject.com/info/search.aspx?aidlst=153">Intermediate</a><a href="http://www.codeproject.com/info/search.aspx?aidlst=252">Swing</a> <p>Reusable extension of JPanel with rounded borders, shadow and antialiasing <p>Sponsored Links <ul> <li><a href="http://www.codeproject.com/KB/java/rounded-jpanel/RoundedJpanel.zip">Download source - 1.91 KB</a></li></ul> <h4>Introduction</h4> <p><a name="result_box1"></a>Swing Framework extensibility allows us to create very advanced graphics component for a better view of our <strong>Jframe</strong>s more than directly Look&amp;Feel management, and more simply. <p>Basically a <code>JComponent </code>is a void Bounded Box that can be added into swing containers.  <p>It can be extended by a simple plain class, and overriding <code><em>paintComponent </em></code>method, we can draw everything we need in a Bounded Box. In this way we can re-create all basic swing components like Buttons, Labels, Panels... with relative events. <h4>Using the Code </h4> <p><a name="result_box2"></a>In this case, we will review a <code>JPanel </code>extension (instead of <code>JComponent </code>extension) because we want to create a <code>Container </code>component (like <code>JPanel</code>!) but with some graphics improvements:  <p><img src="http://www.codeproject.com/images/minus.gif" width="9" height="9"> Collapse<pre>public class RoundedPanel extends JPanel {

    /** Stroke size. it is recommended to set it to 1 for better view */
    protected int strokeSize = 1;
    /** Color of shadow */
    protected Color shadowColor = Color.black;
    /** Sets if it drops shadow */
    protected boolean shady = true;
    /** Sets if it has an High Quality view */
    protected boolean highQuality = true;
    /** Double values for Horizontal and Vertical radius of corner arcs */
    protected Dimension arcs = new Dimension(20, 20);
    /** Distance between shadow border and opaque panel border */
    protected int shadowGap = 5;
    /** The offset of shadow.  */
    protected int shadowOffset = 4;
    /** The transparency value of shadow. ( 0 - 255) */
    protected int shadowAlpha = 150;

	//FOLLOWING CODES GOES HERE
} </pre>
<p>We have created a simple class extending JPanel. It has some properties for the improvements (see inline comments for properties descriptions).
<p><strong>Attention!!</strong> If you want to use this class directly in a visual GUI editor, like integrated Netbeans Editor, we must write a <code>void </code>constructor, because Editor can't directly know constructor parameter of our components: 
<p><img src="http://www.codeproject.com/images/minus.gif" width="9" height="9"> Collapse<pre> public RoundedPanel() {
        super();
        setOpaque(false);
    }</pre>
<p>We call <code>super() </code>father constructor and <code>setOpaque<em>(false)</em></code> to create a transparent <code>void </code>bounded box, where we can freely draw custom component.
<p>Now we can override the <code>paintComponent </code>method:
<p><img src="http://www.codeproject.com/images/minus.gif" width="9" height="9"> Collapse<pre> @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int width = getWidth();
        int height = getHeight();
        int shadowGap = this.shadowGap;
        Color shadowColorA = new Color(shadowColor.getRed(), 
	shadowColor.getGreen(), shadowColor.getBlue(), shadowAlpha);
        Graphics2D graphics = (Graphics2D) g;

        //Sets antialiasing if HQ.
        if (highQuality) {
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
			RenderingHints.VALUE_ANTIALIAS_ON);
        }

        //Draws shadow borders if any.
        if (shady) {
            graphics.setColor(shadowColorA);
            graphics.fillRoundRect(
                    shadowOffset,// X position
                    shadowOffset,// Y position
                    width - strokeSize - shadowOffset, // width
                    height - strokeSize - shadowOffset, // height
                    arcs.width, arcs.height);// arc Dimension
        } else {
            shadowGap = 1;
        }

        //Draws the rounded opaque panel with borders.
        graphics.setColor(getBackground());
        graphics.fillRoundRect(0, 0, width - shadowGap, 
		height - shadowGap, arcs.width, arcs.height);
        graphics.setColor(getForeground());
        graphics.setStroke(new BasicStroke(strokeSize));
        graphics.drawRoundRect(0, 0, width - shadowGap, 
		height - shadowGap, arcs.width, arcs.height);

        //Sets strokes to default, is better.
        graphics.setStroke(new BasicStroke());
    }</pre>
<p>The method has five macro sections. The header section calls super overridden method and declares main variables: (<code>width</code>, <code>height</code>) are the current size of our component; <code>shadowGap </code>is an override of homonymous property, we will see later why; <code>shadowColor </code>is the color property with transparency added; and <code>graphics </code>is the <code>Graphics </code>object passed by method parameters that represent the canvas where we can paint on (<code>Graphics2D </code>cast is more powerful, see antialiasing). 
<p>The next section checks if <code>highQuality </code>is <code>true</code>, so enable antialiasing on canvas for all shapes drawn after. 
<p>Alike <strong>shady</strong> determinates if component draws shadow. Shadow is a simple <code>roundRect</code>, usually black, with left-top and right-bottom corners parameterized by <code>shadowOffset </code>value.
<p>Above a possible shadow, the component draws the opaque panel with a thin edge. Here the right-top and right bottom positions are parameterized by <code>shadowGap</code>. 
<p>Graphically the order 1) -&gt; 2) -&gt; 3) of layer must be this, due to overlap:
<p><img border="0" hspace="0" alt="screenshot2.PNG" src="http://www.codeproject.com/KB/java/rounded-jpanel/screenshot2_small.PNG" width="640" height="336">
<p>The footer section is used to reset parameters that we have distorted. In fact, if we will not reset strokes, the next component added to this panel will have a distorted border.
<h4>Conclusions </h4>
<p>With these simple few lines, we have created a solid redestributable swing component that look like this:
<p>&nbsp; <p>We can see tree <code>RoundedPanel </code>here: violet, green and blue one, each with a different <strong>arcs</strong> dimension that determinates the curvature of corners. The best size is [10,10] like blue panel, because an excessive curve (like violet) can cut out upper-inner components (try set [80,80] .. ).
<h4>License</h4>
<p>This article, along with any associated source code and files, is licensed under <a href="http://www.opensource.org/licenses/apache2.0.php">The Apache License, Version 2.0</a>
<h4>About the Author</h4><img src ="http://www.blogjava.net/cherishchen/aggbug/346666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-21 10:25 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/21/346666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Use setImageObserver of ImageIcon to show animated gif</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/10/346080.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Thu, 10 Mar 2011 06:10:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/10/346080.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/346080.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/10/346080.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/346080.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/346080.html</trackback:ping><description><![CDATA[<p>&nbsp;</p> <p><a href="http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/ImageIcon.html#setImageObserver(java.awt.image.ImageObserver)">ImageIcon (Java 2 Platform SE v1.4.2)</a></p> <h2>setImageObserver</h2><pre>public void <b>setImageObserver</b>(<a href="http://download.oracle.com/javase/1.4.2/docs/api/java/awt/image/ImageObserver.html">ImageObserver</a> observer)</pre>
<dl>
<dd>Sets the image observer for the image. Set this property if the ImageIcon contains an animated GIF, so the observer is notified to update its display. For example: <pre>     icon = new ImageIcon(...)
     button.setIcon(icon);
     icon.setImageObserver(button);
 </pre>
<dd>
<dl></dl>
<dd>
<dl>
<dt><b>Parameters:</b>
<dd><code>observer</code> - the image observer</dd></dl></dd></dl><img src ="http://www.blogjava.net/cherishchen/aggbug/346080.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-10 14:10 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/10/346080.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>The synchronized keyword in Java: synchronization with main memory</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/08/345938.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 08 Mar 2011 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/08/345938.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/345938.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/08/345938.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/345938.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/345938.html</trackback:ping><description><![CDATA[<p>&nbsp;</p> <blockquote> <h3>The <em>synchronized</em> keyword in Java</h3> <h4>What does variable "synchronization with main memory" mean?</h4> <p>For the sake of keeping descriptions short, I'm going to refer a few times to "synchronizing" cached copies of variables with "main memory". Firstly, by "main memory" we mean 'the Java heap, as seen by the JVM'. We don't mean– and don't need to refer to– anything more technical, such as physical RAM as opposed to a CPU cache. We make a distinction between this main memory and other places where we can put values, notably (a) processor registers, in native code produced by a JIT compiler; (b) the set of 'local variable space' that is allocated to every method call; (c) other areas of working memory, not part of the Java heap, that may be allocated locally to a particular thread or thread stack. Now, we've just said that under normal circumstances, the JVM can do a couple of interesting things with variables. Chapter 17 of the Java Language Specification states these and related conditions in more formal terms, albeit in a profoundly incomprehensible way. I'll try and summarise them informally here:  <ul> <li><strong>The JVM is generally free to work on a <em>local copy</em> of a variable. For example, a JIT compiler could create code that loads the value of a Java variable into a register and then works on that register. If this happens, other threads will never see the updated value in the register unless we tell the JVM that they need to. </strong> <li><strong>A JIT compiler (or, for that matter, the bytecode compiler) is generally free to re-order bytecodes or instructions for optimisation purposes, provided that the overall logic of the program is not affected. So, for example, it could delay writing the value from a register back to the "main" copy of a variable belonging to a Java object. </strong></li></ul> <p>The JVM specification effectively says that entering and exiting <tt>synchronized</tt> blocks and methods has to be a "safe barrier" to these operations. If we read and write to variables inside <tt>synchronized</tt> blocks from different threads, we <em>do</em> always expect Thread 1 to see the value set by Thread 2; just seeing a locally cached copy in a register isn't correct. So on entry to and exit from a <tt>synchronized</tt> block, the relevant reads/writes to main memory have to take place, and they have to take place in the correct sequence. We can't re-order the write to take place <em>after</em> we exit the synchronized block, and we can't re-order the read to take place <em>before</em> we enter. In other words, the JVM is <em>not</em> allowed to do this: <pre>LOAD R0, [address of some Java variable]   ; Cache a copy of the variable
<em>enter-synchronization</em>
ADD R0, #1                                 ; Do something with the (cached copy) of the variable
</pre>
<p>or this:<pre><em>enter-synchronized-block</em>
LOAD R0, [address of some Java variable]      ; Cache a copy of the variable
MUL R0, #2                                    ; Do something with it
<em>leave-synchronized-block</em>
STORE R0, [address of variable]               ; Write the new value back to the variable
</pre>
<p>It's possible to say all this in a very obtuse way (as I say, see Chapter 17 of the language spec). But at the end of the day it's kind of common sense: if the whole point of synchronization is to make sure all threads see the updated "master" copy of variables, it's no use updating them after you've left the <tt>synchronized</tt> block. 
<p>In some of the descriptions that follow, we'll refer to "synchronizing cached variables with main memory" and sometimes refer to this as being the source of an overhead. But in fact, some of the overhead is more subtle than this as we've just seen, and comes from the synchronization "barrier" <em>preventing optimisation</em> (code re-ordering). The notion of "synchronization with main memory" is kept essentially to keep our descriptions shorter, but it's important to have seen what's really going on. 
<p>Looking at these details also shows us why without them, we may think that removing synchronization in some cases will work when it's actually incorrect. <strong>A common, but incorrect, "optimisation" is to synchronize when writing to a variable but not on the read. But this is incorrect because without synchronization: (a) the reading thread is not guaranteed to update its working copy of the variable with that in main memory, so may never actually read an updated value of the variable; and (b) even if it does read from main memory, there is nothing to stop it reading while the write method is still in the middle of executing, before it has flushed the value back to main memory. </strong></p></blockquote>
<p><a href="http://www.javamex.com/tutorials/synchronization_concurrency_synchronized2.shtml">The synchronized keyword in Java: synchronization with main memory</a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/345938.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-08 14:40 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/08/345938.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lock and visibility</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/08/345925.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 08 Mar 2011 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/08/345925.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/345925.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/08/345925.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/345925.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/345925.html</trackback:ping><description><![CDATA[<p>Locking is not just about mutual exclusion; it is also about memory visibility. To ensure that all threads see the most up-to-date values of shared mutable variables, the reading and writing threads must synchronize on a common lock. <img src ="http://www.blogjava.net/cherishchen/aggbug/345925.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-08 11:47 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/08/345925.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EventListener</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/07/345860.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Mon, 07 Mar 2011 02:13:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/07/345860.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/345860.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/07/345860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/345860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/345860.html</trackback:ping><description><![CDATA[<p>java.util.EventListener is <strong>marker interface</strong>, which means no method definition in the interface.</p> <p>It’s often used to set up a <strong>hierarchical</strong> <strong>inheritance </strong>relationship.</p><img src ="http://www.blogjava.net/cherishchen/aggbug/345860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-07 10:13 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/07/345860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to Use Models (The Java&amp;trade; Tutorials &amp;gt; Creating a GUI With JFC/Swing &amp;gt; Using Swing Components)</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/07/345857.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Mon, 07 Mar 2011 01:56:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/07/345857.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/345857.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/07/345857.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/345857.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/345857.html</trackback:ping><description><![CDATA[<p>&nbsp;</p> <blockquote> <p>Most Swing components have models. A button (<code>JButton</code>), for example, has a model (a <code>ButtonModel</code> object) that stores the button's state — what its keyboard mnemonic is, whether it's enabled, selected, or pressed, and so on. Some components have multiple models. A list (<code>JList</code>), for example, uses a <code>ListModel</code> to hold the list's contents, and a <code>ListSelectionModel</code> to track the list's current selection.  <p>You often don't need to know about the models that a component uses. For example, programs that use buttons usually deal directly with the <code>JButton</code> object, and don't deal at all with the <code>ButtonModel</code> object.  <p><strong>Why then do models exist? The biggest reason is that they give you flexibility in determining how data is stored and retrieved.</strong> For example, if you're designing a spreadsheet application that displays data in a sparsely populated table, you can create your own table model that is optimized for such use.  <p>Models have other benefits, too. They mean that data isn't copied between a program's data structures and those of the Swing components. <strong>Also, models automatically propagate changes to all interested listeners, making it easy for the GUI to stay in sync with the data.[It’s very important]</strong> For example, to add items to a list you can invoke methods on the list model. When the model's data changes, the model fires events to the <code>JList</code> and any other registered listeners, and the GUI is updated accordingly.  <p>Also, use model to share the application data&nbsp; and sync state automatically between different components. <p>Although Swing's model architecture is sometimes referred to as a Model-View-Controller (MVC) design, it really isn't. Swing components are generally implemented so that the view and controller are indivisible, implemented by a single UI object provided by the look and feel. The Swing model architecture is more accurately described as a <em>separable model architecture</em>. If you're interested in learning more about the Swing model architecture, see <a href="http://java.sun.com/products/jfc/tsc/articles/architecture/">A Swing Architecture Overview</a>, an article in <em>The Swing Connection</em>. </p></blockquote> <p><a href="http://download.oracle.com/javase/tutorial/uiswing/components/model.html">How to Use Models (The Java™ Tutorials &gt; Creating a GUI With JFC/Swing &gt; Using Swing Components)</a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/345857.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-07 09:56 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/07/345857.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Swing Text Render: FontMetrics- base line, ascent,descent</title><link>http://www.blogjava.net/cherishchen/archive/2011/03/04/345740.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Fri, 04 Mar 2011 09:51:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/03/04/345740.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/345740.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/03/04/345740.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/345740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/345740.html</trackback:ping><description><![CDATA[<p><a title="http://java.sun.com/developer/onlineTraining/Media/2DText/other.html#just" href="http://java.sun.com/developer/onlineTraining/Media/2DText/other.html#just">http://java.sun.com/developer/onlineTraining/Media/2DText/other.html#just</a></p> <p><a title="http://download.oracle.com/javase/6/docs/api/java/awt/Rectangle2D" href="http://download.oracle.com/javase/6/docs/api/java/awt/Rectangle2D">http://download.oracle.com/javase/6/docs/api/java/awt/Rectangle2D</a></p> <p>&nbsp;</p> <p><img border="15" hspace="10" alt="The letter 'p' showing its 'reference point'" vspace="7" src="http://download.oracle.com/javase/6/docs/api/java/awt/doc-files/FontMetrics-1.gif"> When an application asks to place a character at the position (<i>x</i>, <i>y</i>), the character is placed so that its reference point (shown as the dot in the accompanying image) is put at that position. The reference point specifies a horizontal line called the <i>baseline</i> of the character. In normal printing, the baselines of characters should align.  <p>&nbsp;</p> <h2>fm.getStringBounds(String, Graphics)</h2> <p>Returns the bounds of the specified <code>String</code> in the specified <code>Graphics</code> context. The bounds is used to layout the <code>String</code>.  <p>This method can be used to get text location information.  <p>Note: The returned bounds is <strong>in baseline-relative coordinates</strong>  <p>&nbsp; <p>Sample, HyperLink Button, the important code: <pre class="csharpcode"><span class="preproc">@Override</span>
    <span class="kwrd">public</span> <span class="kwrd">void</span> paintComponent(Graphics g) {
        <span class="kwrd">if</span>(getAction() == <span class="kwrd">null</span>){
            super.paintComponent(g);
            setFocusable(<span class="kwrd">false</span>);
            <span class="kwrd">return</span>;
        }
        setForeground(Color.BLUE);
        super.paintComponent(g);
        
        Font f = getFont();
        FontMetrics fm = g.getFontMetrics(f);
        Rectangle2D b1 = fm.getStringBounds(getText(), g);
        <span class="rem">// Get the line location.</span>
        <span class="kwrd">double</span> baseY = getHeight() - (getHeight() - b1.getHeight())/2 -1 ;
        <span class="kwrd">double</span> baseX = (getWidth() - b1.getWidth())/2;
        <span class="kwrd">int</span> length =(<span class="kwrd">int</span>)b1.getWidth();
        g.setColor(UISetting.HYPER_LINK_COLOR);
        g.drawLine((<span class="kwrd">int</span>)baseX, (<span class="kwrd">int</span>)baseY, (<span class="kwrd">int</span>)baseX+ length, (<span class="kwrd">int</span>)baseY);
        <span class="kwrd">if</span> (onFocus) {
            g.setColor(UISetting.SELECTED_FOCUS_COLOR);
            <span class="kwrd">double</span> recY = getHeight()/2 - fm.getAscent()/2;
            GraphicUtil.drawDashedRect(g,(<span class="kwrd">int</span>)baseX, (<span class="kwrd">int</span>)recY-1, length, (<span class="kwrd">int</span>)b1.getHeight());
        }
        
    }</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>

<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ce9cb7aa-f29b-41fd-9656-3228eb53be0e" class="wlWriterEditableSmartContent">Technorati 标签: <a href="http://technorati.com/tags/Swing" rel="tag">Swing</a></div><img src ="http://www.blogjava.net/cherishchen/aggbug/345740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-03-04 17:51 <a href="http://www.blogjava.net/cherishchen/archive/2011/03/04/345740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Debugging Java Web Start Applications</title><link>http://www.blogjava.net/cherishchen/archive/2011/02/18/344633.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Fri, 18 Feb 2011 10:32:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/02/18/344633.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/344633.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/02/18/344633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/344633.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/344633.html</trackback:ping><description><![CDATA[<h3>Debugging Java Web Start Applications</h3> <p>Submitted by Dan Dyer on Mon, 2009/02/09 - 9:25am <p>How do you attach a debugger to a Java Web Start application? Normally you probably wouldn’t bother, just start the application without Web Start and debug as normal. However, if you have a bug that shows up only when running in the Web Start sandbox, as I did today, that won’t help.  <p>The SecurityManager restrictions were causing a different branch of my code to be executed than when launching the application from IDEA or the command line. It was not immediately obvious how to attach the debugger to the Web-Started VM. <br>In IDEA, to remotely attach a debugger to the JVM, you should start the VM with following set of switches (or similar):<pre><br>-Xdebug -Xnoagent -Djava.compiler=NONE <br>-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005</pre>
<p>Where do these switches go when launching a Web Start application? Normally you launch the application by just clicking a JNLP link in your browser. One option, which doesn’t work, is to specify the JVM arguments in JNLP file. You can already do something like this:<pre><br>&lt;j2se version="1.5+" java-vm-args="-ea -server"/&gt;<br></pre>
<p> Adding the debug switches is trivial… and futile. The problem is that remote debugging requires the VM to open up a socket to accept connections from the debugger. Rather sensibly, Web Start does not permit untrusted applications to open sockets on users’ machines. I don’t know if it would work if the application was signed, I was too lazy to go through the hassle of signing the code. 
<p>If you want to open a socket on the client machine for debugging purposes, you are going to have to do it from the client machine rather than the JNLP file. The solution is to set the JAVAWS_VM_ARGS environment variable to include the debug switches and then to launch the javaws executable and point it at the unmodified JNLP file. From a bash shell it looks like this: 
<p>export JAVAWS_VM_ARGS="-Xdebug -Xnoagent blah blah" javaws http://www.example.com/path_to/application.jnlp 
<p>You can then attach the debugger as normal. 
<p><em>From </em><a href="http://blog.uncommons.org/"><em>http://blog.uncommons.org/</em></a><img src ="http://www.blogjava.net/cherishchen/aggbug/344633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-02-18 18:32 <a href="http://www.blogjava.net/cherishchen/archive/2011/02/18/344633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Applet and Java web start:  can do and can&amp;rsquo;t do.</title><link>http://www.blogjava.net/cherishchen/archive/2011/01/18/343136.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 18 Jan 2011 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/01/18/343136.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/343136.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/01/18/343136.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/343136.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/343136.html</trackback:ping><description><![CDATA[<h3>Rich Internet Applications Decision Guide</h3> <blockquote> <p>Both applets and Java Web Start applications are considered <i>Rich Internet Applications (RIAs)</i>. Evaluate the following characteristics of applets and Java Web Start applications to decide how to deploy your RIA.  <h6>Applets</h6> <ul> <li>Applets run in the context of a browser.  <li>Applets have access to session cookies and persistent cookies.  <li>Applets can interact with the web page that they are embedded in. Applets can traverse and manipulate the Document Object Model of the web page and interact with JavaScript that is in the web page. JavaScript code can access public methods and variables of an applet.  <li>Applets can be launched using Java Network Launch Protocol (JNLP). When launched using JNLP, unsigned applets are allowed access to persistent storage, download control, file I/O, and more. Applets launched using JNLP have capabilities that are comparable to that of a Java Web Start application.<br><strong>Applets can also be launched without JNLP, in which case, their capabilities might be limited. </strong> <li>Applets can request a particular version of the Java Runtime Environment software for execution. </li></ul> <h6>Java Web Start applications</h6> <ul> <li>Java Web Start applications are launched from a web page the first time. Subsequently, they may be re-launched from the web page or from a desktop shortcut.  <li>Java Web Start applications do not run in the context of a browser. The applications cannot interact with HTML and JavaScript in a web page and have access to persistent cookies only.  <li>Java Web Start applications are allowed access to persistent storage, file I/O, and other client related services.  <li>Java Web Start applications can request a particular version of the Java Runtime Environment software for execution. </li></ul></blockquote><img src ="http://www.blogjava.net/cherishchen/aggbug/343136.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-01-18 11:27 <a href="http://www.blogjava.net/cherishchen/archive/2011/01/18/343136.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Resources about Java Web Start</title><link>http://www.blogjava.net/cherishchen/archive/2011/01/13/342930.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Thu, 13 Jan 2011 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/01/13/342930.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/342930.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/01/13/342930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/342930.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/342930.html</trackback:ping><description><![CDATA[<p>Java Web Start applications are launched by using the Java Network Launch Protocol (JNLP).</p> <p>Java Web Start software provides Java developers and users with many deployment advantages:  <ul> <li>With Java Web Start software, you can place a single Java application on a web server for deployment to a wide variety of platforms, including Windows 2003/Vista/2000/XP, Linux, and Solaris.  <li>Java Web Start software supports multiple, simultaneous versions of the Java platform. An application can request a specific version of the Java Runtime Environment (JRE) software without conflicting with the needs of other applications. Java Web Start software automatically downloads and installs the correct version of the Java platform as necessary based on the application's needs and the user's environment.  <li>Users can create a desktop shortcut to launch a Java Web Start application outside a browser.  <li>Java Web Start software takes advantage of the inherent security of the Java platform. By default, applications have restricted access to local disk and network resources. Users can safely run applications from sources that are not trusted.  <li>Applications launched with Java Web Start software are cached locally for improved performance.  <li>Updates to a Java Web Start application are automatically downloaded when the application is run standalone from the user's desktop. </li></ul> <p>&nbsp;</p> <p>Java web start guide: <a href="http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/contents.html">http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/contents.html</a><br></p> <p>Java web start lesson: </p> <p><a href="http://download.oracle.com/javase/tutorial/deployment/webstart/index.html">http://download.oracle.com/javase/tutorial/deployment/webstart/index.html</a><br></p> <p>JNLP(Java network launching protocol):</p> <p>http://download.oracle.com/javase/tutorial/deployment/deploymentInDepth/jnlpFileSyntax.html</p><img src ="http://www.blogjava.net/cherishchen/aggbug/342930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-01-13 15:35 <a href="http://www.blogjava.net/cherishchen/archive/2011/01/13/342930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>transparent button in swing</title><link>http://www.blogjava.net/cherishchen/archive/2011/01/06/342393.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Wed, 05 Jan 2011 23:01:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2011/01/06/342393.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/342393.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2011/01/06/342393.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/342393.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/342393.html</trackback:ping><description><![CDATA[http://blog.csdn.net/JAVASUI/archive/2008/09/30/3002413.aspx

The key is: 
setContentAreaFilled(false); 
or 
setOpaque(false);
setColor(**);  // must

<img src ="http://www.blogjava.net/cherishchen/aggbug/342393.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2011-01-06 07:01 <a href="http://www.blogjava.net/cherishchen/archive/2011/01/06/342393.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Best practices to improve performance in JDBC</title><link>http://www.blogjava.net/cherishchen/archive/2010/10/15/335204.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Fri, 15 Oct 2010 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/10/15/335204.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/335204.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/10/15/335204.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/335204.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/335204.html</trackback:ping><description><![CDATA[<p>From <a title="http://www.precisejava.com/javaperf/j2ee/JDBC.htm" href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm">http://www.precisejava.com/javaperf/j2ee/JDBC.htm</a> <p>&nbsp; <p>This topic illustrates the best practices to improve performance in JDBC with the following sections: <ul> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC101">Overview of JDBC</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC102">Choosing the right Driver</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC103">Optimization with Connection</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC104">Set optimal row pre-fetch value</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC105">Use Connection pool</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC106">Control transaction</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC107">Choose optimal isolation level</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC108">Close Connection when finished</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC109">Optimization with Statement</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC110">Choose right Statement interface</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC111">Do batch update</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC112">Do batch retrieval using Statement</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC113">Close Statement when finished</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC114">Optimization with ResultSet</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC115">Do batch retrieval using ResultSet</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC116">Setup proper direction of processing rows</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC117">Use proper getxxx() methods</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC118">Close ResultSet when finished</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC119">Optimization with SQL Query</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC120">Cache the read-only and read-mostly data</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC121">Fetch small amount of data iteratively instead of fetching whole data at once</a></p> <li> <p><a href="http://www.precisejava.com/javaperf/j2ee/JDBC.htm#JDBC122">Key Points</a></p></li></ul> <p><a name="JDBC101">Overview of JDBC</a> <p>JDBC defines how a Java program can communicate with a database. This section focuses&nbsp; mainly on JDBC 2.0 API.&nbsp; JDBC API provides two packages they are java.sql and javax.sql . By using JDBC API, you can connect virtually any database, send SQL queries to the database and process the results.  <p>JDBC architecture defines different layers to work with any database and java, they are JDBC API interfaces and classes which are at top most&nbsp; layer( to work with java ), a driver which is at middle layer (implements the JDBC API interfaces that maps java to database specific language) and a database which is at the bottom (to store physical data). The following figure illustrates the JDBC architecture. <p><img alt="" src="http://www.precisejava.com/javaperf/j2ee/JDBC_files/image002.gif"> <p>JDBC API provides interfaces and classes to work with databases. Connection interface encapsulates database connection functionality, Statement interface encapsulates SQL query representation and execution functionality and ResultSet interface encapsulates retrieving data which comes from execution of SQL query using Statement.  <p>The following are the basic steps to write a JDBC program <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Import java.sql and javax.sql packages <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Load JDBC driver <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. Establish connection to the database using Connection interface <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. Create a Statement by passing SQL query <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5. Execute the Statement <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6. Retrieve results by using ResultSet interface <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7. Close Statement and Connection <p>We will look at these areas one by one, what type of driver you need to load, how to use Connection interface in the best manner, how to use different Statement interfaces, how to process results using ResultSet and finally how to optimize SQL queries to improve JDBC performance. <p>Note1: Your JDBC driver should be fully compatible with JDBC 2.0 features in order to use some of the suggestions mentioned in this section. <p>Note2: This Section assumes that reader has some basic knowledge of JDBC. <p><b><a name="JDBC102">Choosing right Driver</a> </b> <p>Here we will walk through initially about the types of drivers, availability of drivers, use of drivers in different situations, and then we will discuss about which driver suits your application best. <p>Driver is the key player in a JDBC application, it acts as a mediator between Java application and database. It implements JDBC API interfaces for a database, for example Oracle driver for oracle database, Sybase driver for Sybase database. It maps Java language to database specific language including SQL. <p>JDBC defines four types of drivers to work with. Depending on your requirement you can choose one among&nbsp; them. <p>Here is a brief description of each type of driver : <p>Type of driver<br>Tier<br>Driver mechanism<br>Description <p>1<br>Two<br>JDBC-ODBC<br>This driver converts JDBC calls to ODBC calls through JDBC-ODBC Bridge driver which in turn converts to database calls. Client requires ODBC libraries. <p>2<br>Two<br>Native API - Partly - Java driver<br>This driver converts JDBC calls to database specific native calls. Client requires database specific libraries.  <p>3<br>Three<br>JDBC - Net -All Java driver<br>This driver passes calls to proxy server through network protocol which in turn converts to database calls and passes through database specific protocol. Client doesn't require any driver. <p>4<br>Two<br>Native protocol - All - Java driver<br>This driver directly calls database. Client doesn't require any driver. <p>Obviously the choice of choosing a driver depends on availability of driver and requirement. Generally all the databases support their own drivers or from third party vendors. If you don't have driver for your database, JDBC-ODBC driver is the only choice because all most all the vendors support ODBC. If you have tiered requirement ( two tier or three tier) for your application, then you can filter down your&nbsp; choices, for example if your application is three tiered, then you can go for Type three driver between client and proxy server shown below. If you want to connect to database from java applet, then you have to use Type four driver because it is only the driver which supports that feature. This figure shows the overall picture of drivers from tiered perspective. <p><img alt="" src="http://www.precisejava.com/javaperf/j2ee/JDBC_files/image004.gif"> <p>This figure illustrates the drivers that can be used for two tiered and three tiered applications. For both two and three tiered applications, you can filter down easily to Type three driver but you can use Type one, two and four drivers for both tiered applications. To be more precise, for java applications( non-applet) you can use Type one, two or four driver. Here is exactly where you may make a mistake by&nbsp; choosing a driver without taking performance into consideration. Let us look at that perspective in the following section. <p>Type 3 &amp; 4 drivers are faster than other drivers because Type 3 gives facility for optimization techniques provided by application server such as connection pooling, caching, load balancing etc and Type 4 driver need not translate database calls to ODBC or native connectivity interface. Type 1 drivers are slow because they have to convert JDBC calls to ODBC through JDBC-ODBC Bridge driver initially and then ODBC Driver converts them into database specific calls. Type 2 drivers give average performance when compared to Type 3 &amp; 4 drivers because the database calls have to be converted into database specific calls. Type 2 drivers give better performance than Type 1 drivers.  <p>Finally, to improve performance  <p>1. Use Type 4 driver for applet to database communication. <p>2. Use Type 2 driver for two tiered applications for communication between java client and the database that gives better performance when compared to Type1 driver <p>3. Use Type 1 driver if your database doesn't support a driver. This is rare situation because almost all major databases support drivers or you will get them from third party vendors. <p>4.Use Type 3 driver to communicate between client and proxy server ( weblogic, websphere etc) for three tiered applications that gives better performance when compared to Type 1 &amp; 2 drivers. <p><b><a name="JDBC103">Optimization with Connection</a></b> <p>java.sql package in JDBC provides Connection interface that encapsulates database connection functionality. Using Connection interface, you can fine tune the following operations : <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Set optimal row pre-fetch value <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Use Connection pool <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. Control transaction <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. Choose optimal isolation level <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5. Close Connection when finished <p>Each of these operations effects the performance. We will walk through each operation one by one. <p><b><a name="JDBC104">1. Set optimal row pre-fetch value</a></b> <p>We have different approaches to establish a connection with the database, the first type of approach is :  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. DriverManager.getConnection(String url) <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. DriverManager.getConnection(String url, Properties props) <p><b></b>&nbsp;&nbsp;&nbsp; 3. DriverManager.getConnection(String url, String user, String password) <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. Driver.connect(String url, Properties props) <p>When you use this approach, you can pass database specific information to the database by passing properties using Properties object to improve performance. For example, when you use oracle database you can pass default number of rows that must be pre-fetched from the database server and the default batch value that triggers an execution request. Oracle has default value as 10 for both properties. By increasing the value of these properties, you can reduce the number of database calls which in turn improves performance. The following code snippet illustrates this approach. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Properties props = new java.util.Properties(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.put("user","scott"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.put("password","tiger"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.put("defaultRowPrefetch","30"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; props.put("defaultBatchValue","5"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection con = DriverManger.getConnection("jdbc:oracle:thin:@hoststring", props);  <p>You need to figure out appropriate values for above properties for better performance depending on application's requirement. Suppose, you want to set these properties for search facility, you can increase defaultRowPrefetch so that you can increase performance significantly. <p>The second type of approach is to get connection from DataSource. <p>You can get the connection using javax.sql.DataSource interface. The advantage of getting connection from this approach is that the DataSource works with JNDI. The implementation of DataSource is done by vendor, for example you can find this feature in weblogic, websphere etc. The vendor simply creates DataSource implementation class and binds it to the JNDI tree. The following code shows how a vendor creates implementation class and binds it to JNDI tree. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataSourceImpl dsi = new DataSourceImpl(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dsi.setServerName("oracle8i"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dsi.setDatabaseName("Demo"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context ctx = new InitialContext(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctx.bind("jdbc/demoDB", dsi); <p>This code registers the DataSourceImpl object to the JNDI tree, then the programmer can get the DataSource reference from JNDI tree without knowledge of the underlying technology. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context ctx = new InitialContext(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataSource ds = (DataSource)ctx.lookup("jdbc/demoDB"); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection con = ds.getConnection(); <p>By using this approach we can improve performance. Nearly all major vendor application servers like weblogic, webshpere implement the DataSource by taking connection from connection pool rather than a single connection every time. The application server creates connection pool by default. We will discuss the advantage of connection pool to improve performance in the next section. <p><b><a name="JDBC105">2. Use Connection pool</a></b> <p>Creating a connection to the database server is expensive. It is even more expensive if the server is located on another machine. Connection pool contains a number of open database connections with minimum and maximum connections, that means the connection pool has open connections between minimum and maximum number that you specify. The pool expands and shrinks between minimum and maximum size depending on incremental capacity. You need to give minimum, maximum and incremental sizes as properties to the pool in order to maintain that functionality. You get the connection from the pool rather directly .For example, if you give properties like min, max and incremental sizes as 3, 10 and 1 then pool is created with size 3 initially and if it reaches it's capacity 3 and if a client requests a connection concurrently, it increments its capacity by 1 till it reaches 10 and later on it puts all its clients in a queue.&nbsp; <p>There are a few choices when using connection pool.  <p>1. You can depend on application server if it supports this feature, generally all the application servers support connection pools. Application server creates the connection pool on behalf of you when it starts. You need to give properties like min, max and incremental sizes to the application server.  <p>2. You&nbsp; can use JDBC 2.0 interfaces, ConnectionPoolDataSource and PooledConnection if your driver implements these interfaces <p>3. Or&nbsp; you can create your own connection pool if you are not using any application server or JDBC 2.0&nbsp; compatible driver. <p>By using any of these options, you can increase performance significantly. You need to take care of properties like min, max and incremental sizes. The maximum number of connections to be given depends on your application's&nbsp; requirement that means how many concurrent clients can access&nbsp; your database and also it depends up on your database's capability to provide maximum number of connections.  <p><b><a name="JDBC106">3. Control transaction</a></b> <p>In general, transaction represents one unit of work or bunch of code in the program that executes in it's entirety or none at all. To be precise, it is all or no work. In JDBC, transaction is a set of one or more Statements that execute as a single unit. <p>java.sql.Connection interface provides some methods to control transaction they are <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public interface Connection { <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean getAutoCommit(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setAutoCommit(boolean autocommit); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; commit(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rollback();  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <p>JDBC's default mechanism for transactions: <p>By default in JDBC transaction starts and commits after each statement's&nbsp; execution on a connection. That is the AutoCommit mode is true. Programmer need not write a commit() method explicitly after each statement. <p>Obviously this default mechanism gives good facility for programmers if they want to execute a single statement. But it gives poor performance when multiple statements on a connection are to be executed because commit is issued after each statement by default, that in turn reduces performance by issuing unnecessary commits. The remedy is to flip it back to AutoCommit mode as false and issue commit() method after a set of statements execute, this is called as batch transaction. Use rollback() in catch block to rollback the transaction whenever an exception occurs in your program. The following code illustrates the batch transaction approach. <p>try{ <p>&nbsp;&nbsp;&nbsp; connection.setAutoCommit(false);  <p>&nbsp;&nbsp;&nbsp; PreparedStatement ps = connection.preareStatement( "UPDATE employee SET Address=? WHERE name=?"); <p>&nbsp;&nbsp;&nbsp; ps.setString(1,"Austin"); <p>&nbsp;&nbsp;&nbsp; ps.setString(2,"RR"); <p>&nbsp;&nbsp;&nbsp; ps.executeUpdate(); <p>&nbsp;&nbsp;&nbsp; PreparedStatement ps1 = connection.prepareStatement( "UPDATE account SET salary=? WHERE name=?"); <p>&nbsp;&nbsp;&nbsp; ps1.setDouble(1, 5000.00); <p>&nbsp;&nbsp;&nbsp; ps1.setString(2,"RR"); <p>&nbsp;&nbsp;&nbsp; ps1.executeUpdate(); <p>&nbsp;&nbsp;&nbsp; connection.commit(); <p>&nbsp;&nbsp;&nbsp; connection.setAutoCommit(true); <p>&nbsp;&nbsp;&nbsp; }catch(SQLException e){ connection.rollback();} <p>&nbsp;&nbsp;&nbsp; finally{ <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ps != null){ ps.close();} <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ps1 != null){ps1.close();} <blockquote> <p>&nbsp;&nbsp; if(connection != null){connection.close();}</p></blockquote> <p>&nbsp;&nbsp;&nbsp; } <p>This batch transaction gives good performance by reducing commit calls after each statement's execution. <p><b><a name="JDBC107">4. Choose optimal isolation level</a></b> <p>Isolation level represent how a database maintains data integrity against the problems like dirty reads, phantom reads and non-repeatable reads which can occur due to concurrent transactions. java.sql.Connection interface provides&nbsp; methods and constants to avoid the above mentioned problems by setting different isolation levels. <p>public interface Connection { <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int&nbsp; TRANSACTION_NONE&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 <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int&nbsp; TRANSACTION_READ_COMMITTED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 2 <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int&nbsp; TRANSACTION_READ_UNCOMMITTED&nbsp;&nbsp;&nbsp;&nbsp; = 1 <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int&nbsp; TRANSACTION_REPEATABLE_READ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4 <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int&nbsp; TRANSACTION_SERIALIZABLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 8 <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getTransactionIsolation(); <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setTransactionIsolation(int isolationlevelconstant); <p>} <p>You can get the existing isolation level with getTransactionIsolation() method and set the isolation level with setTransactionIsolation(int isolationlevelconstant) by passing above constants to this method. <p>The following table describes isolation level against the problem that it prevents : <p>Transaction Level&nbsp; <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; Permitted Phenomena <br>Performance impact <p>&nbsp;&nbsp;&nbsp; Dirty reads&nbsp; <br> Non&nbsp; Repeatable reads<br>Phantom reads <p>TRANSACTION_NONE<br> N/A<br>N/A<br>N/A<br>FASTEST <p>TRANSACTION_READ_UNCOMMITED<br>YES<br>YES<br>YES<br>FASTEST <p>TRANSACTION_READ_COMMITED<br>NO <br>YES<br>YES<br>FAST <p>TRANSACTION_REPEATABLE_READ<br>NO<br>NO<br>YES<br>MEDIUM <p>TRANSACTION_SERIALIZABLE<br>NO<br>NO <br>NO<br>SLOW <p>YES means that the Isolation level does not prevent the problem <p>NO means that the Isolation level prevents the problem <p>By setting isolation levels, you are having an impact on the performance as mentioned in the above table. Database use read and write locks to control above isolation levels. Let us have a look at each of these problems and then look at the impact on the performance.  <p><b>Dirty read problem :</b> <p>The following figure illustrates Dirty read problem&nbsp; : <p><img alt="" src="http://www.precisejava.com/javaperf/j2ee/JDBC_files/image006.gif"> <p>Step 1:&nbsp;&nbsp;&nbsp;&nbsp; Database row has PRODUCT = A001 and PRICE = 10 <p>Step 2:&nbsp;&nbsp;&nbsp; Connection1 starts&nbsp; Transaction1 (T1) . <p>Step 3:&nbsp;&nbsp;&nbsp; Connection2 starts&nbsp; Transaction2 (T2) . <p>Step 4:&nbsp;&nbsp;&nbsp; T1 updates PRICE =20 for PRODUCT = A001 <p>Step 5:&nbsp;&nbsp;&nbsp; Database has now PRICE = 20 for PRODUCT = A001 <p>Step 6:&nbsp;&nbsp;&nbsp; T2 reads PRICE = 20 for PRODUCT = A001 <p>Step 7:&nbsp;&nbsp;&nbsp; T2 commits transaction <p>Step 8:&nbsp;&nbsp;&nbsp; T1 rollbacks the transaction because of some problem <p>The problem is that T2 gets wrong PRICE=20 for PRODUCT = A001 instead of 10 because of uncommitted read. Obviously it is very dangerous in critical transactions if you read inconsistent data. If you&nbsp; are sure about not accessing data concurrently&nbsp; then you can allow this problem by setting TRANSACTION_READ_UNCOMMITED or TRANSACTION_NONE that in turn improves performance otherwise you have to use TRANSACTION_READ_COMMITED to avoid this problem. <p><b>Unrepeatable read problem :</b> <p>The following figure illustrates Unrepeatable read problem&nbsp; : <p><img alt="" src="http://www.precisejava.com/javaperf/j2ee/JDBC_files/image008.gif"> <p>Step 1:&nbsp;&nbsp;&nbsp;&nbsp; Database row has PRODUCT = A001 and PRICE = 10 <p>Step 2:&nbsp;&nbsp;&nbsp; Connection1 starts&nbsp; Transaction1 (T1) . <p>Step 3:&nbsp;&nbsp;&nbsp; Connection2 starts&nbsp; Transaction2 (T2) . <p>Step 4:&nbsp;&nbsp;&nbsp; T1 reads PRICE =10 for PRODUCT = A001 <p>Step 5:&nbsp;&nbsp;&nbsp; T2 updates PRICE = 20 for PRODUCT = A001 <p>Step 6:&nbsp;&nbsp;&nbsp; T2 commits transaction <p>Step 7:&nbsp;&nbsp;&nbsp; Database row has PRODUCT = A001 and PRICE = 20 <p>Step 8:&nbsp;&nbsp;&nbsp; T1 reads PRICE = 20 for PRODUCT = A001 <p>Step 9:&nbsp;&nbsp;&nbsp; T1 commits transaction <p>Here the problem is that Transaction1 reads 10 first time and reads 20 second time but it is supposed to be 10 always whenever it reads a record in that transaction. You can control this problem by setting isolation level as TRANSACTION_REPEATABLE_READ. <p><b>Phantom read problem :</b> <p>The following figure illustrates Phantom read problem&nbsp; : <p><img alt="" src="http://www.precisejava.com/javaperf/j2ee/JDBC_files/image010.gif"> <p>Step 1:&nbsp;&nbsp;&nbsp;&nbsp; Database has a row PRODUCT = A001 and COMPANY_ID = 10 <p>Step 2:&nbsp;&nbsp;&nbsp; Connection1 starts&nbsp; Transaction1 (T1) . <p>Step 3:&nbsp;&nbsp;&nbsp; Connection2 starts&nbsp; Transaction2 (T2) . <p>Step 4:&nbsp;&nbsp;&nbsp; T1 selects a row with a condition SELECT PRODUCT WHERE COMPANY_ID = 10 <p>Step 5:&nbsp;&nbsp;&nbsp; T2 inserts a row with a condition INSERT PRODUCT=A002&nbsp; WHERE <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COMPANY_ID= 10 <p>Step 6:&nbsp;&nbsp;&nbsp; T2 commits transaction <p>Step 7:&nbsp;&nbsp;&nbsp; Database has 2 rows with that condition <p>Step 8:&nbsp;&nbsp;&nbsp; T1 select again with a condition SELECT PRODUCT WHERE COMPANY_ID=10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and gets 2 rows instead of 1 row <p>Step 9:&nbsp;&nbsp;&nbsp; T1 commits transaction <p>Here the problem is that T1 gets 2 rows instead of 1 row up on selecting the same condition second time. You can control this problem by setting isolation level as TRANSACTION_SERIALIZABLE <p><b>Choosing a right isolation level for your program:</b> <p>Choosing a right isolation level for your program depends upon your application's requirement. In single application itself the requirement generally changes, suppose if you write a program for searching a product catalog from your database then you can easily choose TRANSACTION_READ_UNCOMMITED because you need not worry about the problems that are mentioned above, some other program can insert records at the same time, you don't have to bother much about that insertion. Obviously this improves performance significantly. <p>If you write a critical program like bank or stocks analysis program where you want to control all of the above mentioned problems, you can choose TRANSACTION_SERIALIZABLE for maximum safety. Here it is the tradeoff between the safety and performance. Ultimately we need safety here. <p>If you don't have to deal with concurrent transactions your application, then the best choice is TRANSACTION_NONE to improve performance. <p>Other two isolation levels need good understanding of your requirement. If your application needs only committed records, then TRANSACTION_READ_COMMITED isolation is the good choice. If your application needs to read a row exclusively till you&nbsp; finish your work, then TRANSACTION_REPEATABLE_READ is the best choice. <p><b>Note</b>: Be aware of your database server's support for these isolation levels. Database servers may not support all of these isolation levels. Oracle server supports only two isolation levels, TRANSACTION_READ_COMMITED and TRANSACTION_SERIALIZABLE isolation level, default isolation level is TRANSACTION_READ_COMMITED. <p><b><a name="JDBC108">5. Close Connection when finished</a></b> <p>Closing connection explicitly allows garbage collector to recollect memory as early as possible. Remember that when you use the connection pool, closing connection means that it returns back to the connection pool rather than closing direct connection to the database. <p><b><a name="JDBC109">Optimization with Statement</a></b> <p>Statement interface represents SQL query and execution and they provide number of methods and constants to work with queries. They also provide some methods to fine tune performance. Programmer may overlook these fine tuning methods that result in poor performance. The following are the tips to improve performance by using statement interfaces <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Choose the right Statement interface <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Do batch update <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. Do batch retrieval using Statement <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Close Statement when finished <p><b><a name="JDBC110">1. Choose right Statement interface</a></b> <p>There are three types of Statement interfaces in JDBC to represent the SQL query and execute that query, they are Statement, PreparedStatement and CallableStatement. <p>Statement is used for static SQL statement with no input and output parameters, PreparedStatement is used for dynamic SQL statement with input parameters and CallableStatement is used for dynamic SQL satement with both input and output parameters, but PreparedStatement and CallableStatement can be used for static SQL statements as well. CallableStatement is mainly meant for stored procedures. <p>PreparedStatement gives better performance when compared to Statement because it is pre-parsed and pre-compiled by the database once for the first time and then onwards it reuses the parsed and compiled statement. Because of this feature, it significantly improves performance when a statement executes repeatedly, It reduces the overload incurred by parsing and compiling. <p>CallableStatement gives better performance when compared to PreparedStatement and Statement when there is a requirement for single request to process multiple complex statements. It parses and stores the stored procedures in the database and does all the work at database itself that in turn improves performance. But we loose java portability and we have to depend up on database specific stored procedures.  <p><b><a name="JDBC111">2. Do batch update</a></b> <p>You can send multiple queries to the database at a time using batch update feature of statement objects this reduces the number of JDBC calls and improves performance. Here is an example of how you can do batch update, <p>statement.addBatch( "sql query1"); <p>statement.addBatch(" sql query2"); <p>statement.addBatch(" sql query3"); <p>statement.executeBatch(); <p>All three types of statements have these methods to do batch update. <p><b><a name="JDBC112">3. Do batch retrieval using Statement</a></b> <p>You can get the default number of rows that is provided by the driver. You can improve performance by increasing number of rows to be fetched at a time from database using setFetchSize() method of the statement object. <p>Initially find the default size by using <p>Statement.getFetchSize();&nbsp;&nbsp; and then set the size as per your requirement <p>Statement.setFetchSize(30); <p>Here it retrieves 30 rows at a time for all result sets of this statement. <p><b><a name="JDBC113">4. Close Statement when finished</a></b> <p>Close statement object as soon as you finish working with that, it explicitly gives a chance to garbage collector to recollect memory as early as possible which in turn effects performance.  <p>Statement.close(); <p><b><a name="JDBC114">Optimization with ResultSet</a></b> <p>ResultSet interface represents data that contains the results of executing an SQL Query and it provides a number of methods and constants to work with that data. It also provides methods to fine tune retrieval of data to improve performance. The following are the fine tuning tips to improve performance by using ResultSet interface. <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. Do batch retrieval using ResultSet <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2. Set up proper direction for processing the rows <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3. Use proper get methods <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4. Close ResultSet when finished <p><b><a name="JDBC115">1. Do batch retrieval using ResultSet</a></b> <p>ResultSet interface also provides batch retrieval facility like Statement as mentioned above. It overrides the Statement behaviour. <p>Initially find the default size by using <p>ResultSet.getFetchSize(); and then set the size as per requirement <p>ResultSet.setFetchSize(50); <p>This feature significantly improves performance when you are dealing with retrieval of large number of rows like search functionality.  <p><b><a name="JDBC116">2. Setup proper direction of processing rows</a></b> <p>ResultSet has the capability of setting the direction in which you want to process the results, it has three constants for this purpose, they are <p>FETCH_FORWARD, FETCH_REVERSE, FETCH_UNKNOWN <p>Initially find the direction by using  <p>ResultSet.getFetchDirection(); and then set the direction accordingly <p>ResultSet.setFetchDirection(FETCH_REVERSE); <p><b><a name="JDBC117">3. Use proper getxxx() methods</a></b> <p>ResultSet interface provides lot of getxxx() methods to get and convert database data types to java data types and is flexibile in converting non feasible data types. For example, <p>getString(String columnName) returns java String object. <p>columnName is recommended to be a VARCHAR OR CHAR type of database but it can also be a NUMERIC, DATE etc. <p>If you give non recommended parameters, it needs to cast it to proper java data type that is&nbsp; expensive. For example consider that&nbsp; you select&nbsp; a product's id from huge database which returns millions of records from search functionality, it needs to convert all these records that is very expensive. <p>So always use proper getxxx() methods according to JDBC recommendations. <p><b><a name="JDBC118">4. Close ResultSet when finished</a></b> <p>Close ResultSet object as soon as you finish working with ResultSet object even though Statement object closes the ResultSet object implicitly when it closes, closing ResultSet explicitly gives chance to garbage collector to recollect memory as early as possible because ResultSet object may occupy lot of memory depending on query.  <p>ResultSet.close(); <p><b><a name="JDBC119">Optimization with SQL Query </a></b> <p>This is one of the area where programmers generally make a mistake  <p>If you give a query like <p>Statement stmt = connection.createStatement(); <p>ResultSet rs = stmt.executeQuery("select * from employee where name=RR"); <p>The returned result set contains all the columns data. you may not need all the column data and want only salary for RR. <p>The better query is "select salary from employee where name=RR" <p>It returns the required data&nbsp; and reduces unnecessary data retrieval. <p><b><a name="JDBC120">Cache the read-only and read-mostly data</a></b> <p>Every database schema generally has read-only and read-mostly tables. These tables are called as lookup tables. Read-only tables contain static data that never changes in its life time. Read-mostly tables contain semi dynamic data that changes often. There will not be any sort of writing operations in these tables.  <p>If an application reads data from these tables for every client request, then it is redundant, unnecessary and expensive. The solution for this problem is to cache the read-only table data by reading the data from that table once and caching the read-mostly table data by reading and refreshing with time limit. This solution improves performance significantly. See the following link for source code of such caching mechanism. <p><a href="http://www.javaworld.com/javaworld/jw-07-2001/jw-0720-cache.html">http://www.javaworld.com/javaworld/jw-07-2001/jw-0720-cache.html</a> <p>You can tweak this code as per application requirement. For read-only data, you need not refresh data in its life time. For read-mostly data, you need to refresh the data with time limit. It is better to set this refreshing time limit in properties file so that it can be changed at any time. <p><b><a name="JDBC121">Fetch small amount of data iteratively instead of fetching whole data at once</a></b> <p>Applications generally require to retrieve huge data from the database using JDBC in operations&nbsp; like searching data. If the client request for a search, the application might return the whole result set at once. This process takes lot of time and has an impact on performance. The solution for the problem is <p>1. Cache the search data at the server-side and return the data iteratively to the client. For example, the search returns 1000 records, return data to the client in 10 iterations where each iteration has 100 records. <p>2. Use Stored procedures to return data iteratively. This does not use server-side caching rather server-side application uses Stored procedures to return small amount of data iteratively.  <p>Out of these solutions the second solution gives better performance because it need not keep the data in the cache (in-memory). The first procedure is useful when the total amount of data to be returned is not huge. <p><b><a name="JDBC122">Key Points</a></b> <ol> <li>Use Type two driver for two tiered applications to communicate from java client to database that gives better performance than Type1 driver. <li>Use Type four driver for applet to database communication that is two tiered applications and three tiered applications when compared to other drivers. <li>Use Type one driver if you don't have a driver for your database. This is a rare situation because all major databases support drivers or you will get a driver from third party vendors. <li>Use Type three driver to communicate between client and proxy server ( weblogic, websphere etc) for three tiered applications that gives better performance when compared to Type 1 &amp;2 drivers. <li>Pass database specific properties like defaultPrefetch if your database supports any of them. <li>Get database connection from connection pool rather than getting it directly <li>Use batch transactions. <li>Choose right isolation level as per your requirement. TRANSACTION_READ_UNCOMMITED gives best performance for concurrent transaction based applications. TRANSACTION_NONE gives best performance for non-concurrent transaction based applications. <li>Your database server may not support all isolation levels, be aware of your database server features. <li>Use PreparedStatement when you execute the same statement more than once. <li>Use CallableStatement when you want result from multiple and complex statements for a single request. <li>Use batch update facility available in Statements.  <li>Use batch retrieval facility available in Statements or ResultSet. <li>Set up proper direction for processing rows. <li>Use proper getXXX() methods. <li>Close ResultSet, Statement and Connection whenever you finish your work with them. <li>Write precise SQL queries. <li>Cache read-only and read-mostly tables data. <li>Fetch small amount of data iteratively rather than whole data at once when retrieving large amount of data like searching database etc.</li></ol> <p><ins><ins></ins></ins> <p><b>Feed back</b> <p>We appreciate and welcome your comments on this section. Email commentsZZZ@precisejavaZZZ.com (remove ZZZ which is placed to prevent spam). Please note that we may not be able to reply to all the emails due to huge number of emails that we receive but we appreciate your comments and feedback.  <img src ="http://www.blogjava.net/cherishchen/aggbug/335204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-10-15 10:35 <a href="http://www.blogjava.net/cherishchen/archive/2010/10/15/335204.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How to generate Java Heap dump file</title><link>http://www.blogjava.net/cherishchen/archive/2010/10/12/334524.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 12 Oct 2010 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/10/12/334524.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/334524.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/10/12/334524.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/334524.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/334524.html</trackback:ping><description><![CDATA[<h5>Use Jmap command: </h5> <p>jmap.exe -dump:format=b,file=HeapDump.hprof &lt;pid&gt;, pid can be found from system task manager or ps(linux)</p> <p>&nbsp;</p> <h5>Generate automatically when Java heap space out of memory</h5> <p>Add JVM options, -XX:-HeapDumpOnOutOfMemoryError</p> <p>Where the file loaction?</p> <p>After that, you can use visualVM or MAT(Eclipse), or other tools to open it.</p> <p>&nbsp;</p> <h4>VisualVM heap memory setting</h4> <p>on Windows, if you want to increase the memory for the Visual VM tool, you must can do it from in the file<br>%JDK_HOME%\lib\visualvm\etc\visualvm.conf<br>changing the <strong>default_options</strong> property<img src ="http://www.blogjava.net/cherishchen/aggbug/334524.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-10-12 11:08 <a href="http://www.blogjava.net/cherishchen/archive/2010/10/12/334524.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSF Navigation Rule</title><link>http://www.blogjava.net/cherishchen/archive/2010/10/09/334070.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Sat, 09 Oct 2010 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/10/09/334070.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/334070.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/10/09/334070.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/334070.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/334070.html</trackback:ping><description><![CDATA[<h2>Re-direct</h2> <p>Normally, when a Redirect is encountered by the Server, then the current request is terminated, the control is directed back to the browser and the Browser makes the request (which will be available as a URL in the Redirect instruction). The same happens here also. For example, consider the following code snippet, <pre><code>
&lt;navigation-case&gt;
    &lt;from-outcome&gt;loginFailure&lt;/from-outcome&gt;
    &lt;to-view-id&gt;/loginFailure.jsp&lt;/to-view-id&gt;
    &lt;redirect/&gt;
&lt;/navigation-case&gt;
</code>
</pre>
<h3>Specifying wild-cards</h3>
<p>It is also possible to specify wild-card character (*) in the <code>'from-view-id'</code> element. For example, say that we want to handle the navigation mechanism for all jsf files within the folder <code>'registration'</code>, then we can have something like the following, <pre><code>
&lt;navigation-rule&gt;
    &lt;from-view-id&gt;/registration/*&lt;/from-view-id&gt;
    &lt;navigation-case&gt;
        ...
    &lt;/navigation-case&gt;
&lt;/navigation-rule&gt;
</code></pre>
<h3><code>Other</code></h3>
<p>The from-outcome element for the second navigation-case is missing. This means that all outcomes except sayHello, will be forwarded to /pages/goodbye.jsp </p><pre>&lt;navigation-rule&gt; 
   &lt;from-view-id&gt;/pages/inputname.jsp&lt;/from-view-id&gt; 
    &lt;navigation-case&gt; 
      &lt;from-outcome&gt;sayHello&lt;/from-outcome&gt; 
      &lt;to-view-id&gt;/pages/greeting.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
    &lt;navigation-case&gt; 
      &lt;to-view-id&gt;/pages/goodbye.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
  &lt;/navigation-rule&gt;  
  </pre>
<h3>"Global" Outcomes</h3><pre>&lt;navigation-rule&gt; 
    &lt;from-view-id&gt;*&lt;/from-view-id&gt; 
    &lt;navigation-case&gt; 
      &lt;from-outcome&gt;globalhelp&lt;/from-outcome&gt; 
      &lt;to-view-id&gt;/menu/generalHelp.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
&lt;/navigation-rule&gt; 
</pre><pre>or</pre><pre>&lt;navigation-rule&gt; 
    &lt;navigation-case&gt; 
      &lt;from-outcome&gt;globalhelp&lt;/from-outcome&gt; 
      &lt;to-view-id&gt;/menu/generalHelp.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
  &lt;/navigation-rule&gt; 
</pre>
<h2>Navigation Rules in Action </h2><pre>&lt;h:commandButton id="submit" action="sayHello" value="Submit" /&gt; 
The action attribute will be used as an outcome.</pre>
<p>Or, here is another variation:<pre>&lt;h:commandButton id="submit" action="#{GetNameBean.helloAction}" value="Submit" /&gt; </pre><pre>&nbsp;</pre>
<p>The JSF configuration file contains the following code:<pre>&lt;navigation-rule&gt; 
   &lt;from-view-id&gt;/pages/inputname.jsp&lt;/from-view-id&gt; 
    &lt;navigation-case&gt; 
      &lt;from-outcome&gt;sayHello&lt;/from-outcome&gt; 
      &lt;to-view-id&gt;/a.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
  &lt;/navigation-rule&gt; 

&lt;navigation-rule&gt; 
   &lt;from-view-id&gt;/pages/*&lt;/from-view-id&gt; 
    &lt;navigation-case&gt; 
     <strong> &lt;from-action&gt;#{GetNameBean.helloAction}&lt;/from-action&gt;</strong> 
      &lt;from-outcome&gt;sayHello&lt;/from-outcome&gt; 
      &lt;to-view-id&gt;/b.jsp&lt;/to-view-id&gt; 
    &lt;/navigation-case&gt; 
  &lt;/navigation-rule&gt;  

</pre><img src ="http://www.blogjava.net/cherishchen/aggbug/334070.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-10-09 11:27 <a href="http://www.blogjava.net/cherishchen/archive/2010/10/09/334070.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>About Tomcat Context Containers</title><link>http://www.blogjava.net/cherishchen/archive/2010/10/09/334049.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Sat, 09 Oct 2010 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/10/09/334049.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/334049.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/10/09/334049.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/334049.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/334049.html</trackback:ping><description><![CDATA[<p>How to set a Application as&nbsp; Root Context of tomcat</p> <p><a title="http://www.mulesoft.com/tomcat-context" href="http://www.mulesoft.com/tomcat-context">http://www.mulesoft.com/tomcat-context</a></p> <p><a title="http://www.cnblogs.com/daition/archive/2010/05/18/1737876.html" href="http://www.cnblogs.com/daition/archive/2010/05/18/1737876.html">http://www.cnblogs.com/daition/archive/2010/05/18/1737876.html</a></p> <p><a title="http://www.xinotes.org/notes/note/690/" href="http://www.xinotes.org/notes/note/690/">http://www.xinotes.org/notes/note/690/</a></p> <p>You might think that creating a <code>context.xml</code> under <code>META-INF</code> of the WAR file would also work, <b>it doesn't</b>. The path attribute is <a href="http://tomcat.apache.org/tomcat-6.0-doc/config/context.html">ignored unless specified in server.xml</a>.</p><img src ="http://www.blogjava.net/cherishchen/aggbug/334049.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-10-09 10:42 <a href="http://www.blogjava.net/cherishchen/archive/2010/10/09/334049.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决MySQL 5数据库连接超时问题</title><link>http://www.blogjava.net/cherishchen/archive/2010/10/09/334047.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Sat, 09 Oct 2010 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/10/09/334047.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/334047.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/10/09/334047.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/334047.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/334047.html</trackback:ping><description><![CDATA[<h5><a title="http://database.51cto.com/art/200903/116216.htm" href="http://database.51cto.com/art/200903/116216.htm">http://database.51cto.com/art/200903/116216.htm</a></h5> <p>wait_timeout的最大值分别是24天/365天(windows/linux)。以windows为 例，假设我们要将其设为21天，我们只要修改mysql5的配置文件“my.ini”(mysql5 installation dir)，增加一行：wait_timeout=1814400</p><img src ="http://www.blogjava.net/cherishchen/aggbug/334047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-10-09 10:34 <a href="http://www.blogjava.net/cherishchen/archive/2010/10/09/334047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unicast VS Broadcast VS Multicast(转）</title><link>http://www.blogjava.net/cherishchen/archive/2010/08/10/328425.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 10 Aug 2010 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/08/10/328425.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/328425.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/08/10/328425.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/328425.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/328425.html</trackback:ping><description><![CDATA[<p>摘自</p> <p><a title="http://blog.csdn.net/leesphone/archive/2008/03/03/2143954.aspx" href="http://blog.csdn.net/leesphone/archive/2008/03/03/2143954.aspx">http://blog.csdn.net/leesphone/archive/2008/03/03/2143954.aspx</a></p> <p>谢谢这位兄弟。</p> <p>&nbsp;</p> <p><a href="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/UnicastVSBroadcastVSMulticast_EA12/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/UnicastVSBroadcastVSMulticast_EA12/image_thumb.png" width="637" height="685"></a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/328425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-08-10 16:38 <a href="http://www.blogjava.net/cherishchen/archive/2010/08/10/328425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redirect vs forward</title><link>http://www.blogjava.net/cherishchen/archive/2010/08/10/328413.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 10 Aug 2010 06:33:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/08/10/328413.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/328413.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/08/10/328413.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/328413.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/328413.html</trackback:ping><description><![CDATA[<p><a href="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/redirectvsforward_CCC7/image_2.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/redirectvsforward_CCC7/image_thumb.png" width="950" height="193"></a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/328413.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-08-10 14:33 <a href="http://www.blogjava.net/cherishchen/archive/2010/08/10/328413.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>interview question</title><link>http://www.blogjava.net/cherishchen/archive/2010/08/09/328345.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Mon, 09 Aug 2010 14:53:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/08/09/328345.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/328345.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/08/09/328345.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/328345.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/328345.html</trackback:ping><description><![CDATA[Q 08: How does the Object Oriented approach improve software development? DC<br />
A 08: The key benefits are:<br />
Re-use of previous work: <strong>using implementation inheritance and object composition.</strong><br />
Real mapping to the problem domain: Objects map to real world and represent vehicles, customers,<br />
products etc: with encapsulation.<br />
Modular Architecture: Objects, systems, frameworks etc are the building blocks of larger systems.<br />
The increased quality and reduced development time are the by-products of the key benefits discussed above.<br />
If 90% of the new application consists of proven existing components then only the remaining 10% of the code<br />
have to be tested from scratch.<br />
<br />
<img src ="http://www.blogjava.net/cherishchen/aggbug/328345.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-08-09 22:53 <a href="http://www.blogjava.net/cherishchen/archive/2010/08/09/328345.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Creating multi-threaded Swing apps that consume web services</title><link>http://www.blogjava.net/cherishchen/archive/2010/08/09/328310.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Mon, 09 Aug 2010 06:15:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/08/09/328310.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/328310.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/08/09/328310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/328310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/328310.html</trackback:ping><description><![CDATA[<p><a title="http://developerlife.com/tutorials/?p=15" href="http://developerlife.com/tutorials/?p=15">http://developerlife.com/tutorials/?p=15</a></p> <p><small>Posted January 8th, 2007 by <a href="http://developerlife.com/tutorials/?author=2">Nazmul</a></small></p> <p>&nbsp;</p> <p><a href="http://developerlife.com/tutorials/?p=15#overview">Overview</a><br><a href="http://developerlife.com/tutorials/?p=15#background">Background</a><br><a href="http://developerlife.com/tutorials/?p=15#strategy1">Strategy #1: Leverage Swing provided background threads (SwingWorker tasks) only</a><br><a href="http://developerlife.com/tutorials/?p=15#strategy2">Strategy #2: Create your own threads to perform one-shot tasks, and coordinate with SwingWorker tasks</a><br><a href="http://developerlife.com/tutorials/?p=15#strategy3">Strategy #3: Create your own threads to perform recurring/long running tasks, and coordinate with SwingWorker tasks </a> <h3><a name="overview"></a>Overview</h3> <p>If you’ve ever want to incorporate web services into your graphical applications/applets/widgets written in Java, then there are some threading issues that you have to be mindful of, and design around. This tutorial will guide you though some of the important threading issues you have to keep in mind when building such applications. The strategies outlined in this tutorial apply to accessing more than just web services from Swing apps; it also applies to loading information from databases, and performing any other kind of time consuming process that has to happen in the desktop app and interact with it, but can’t make the user interface unresponsive. <p>You can learn more about threads in <a href="http://my.safaribooksonline.com/0321349601/part01?cid=2008_developerlife_SOA_link">this chapter</a> of the Concurrency in Practice book (<a href="http://developerlife.com/reviews/?p=103">on Safari Books Online</a>). You can learn more about the Event Dispatch Thread (EDT) in <a href="http://my.safaribooksonline.com/9780132413930/ch02lev1sec1?imagepage=16&amp;cid=2008_developerlife_RIA_link">this chapter </a>of the Filthy Rich Clients (<a href="http://developerlife.com/reviews/?p=103">on Safari Books Online</a>). <h3><a name="background"></a>Background</h3> <p>For some more background information on Swing applications and threading, read this article – <a href="http://java.sun.com/docs/books/tutorial/uiswing/concurrency/">Lesson: Concurrency in Swing</a>. The Swing framework is essentially single threaded, as are most GUI toolkits. The main thread which updates the UI is called the Event Dispatch Thread (EDT). All the graphical components are created by this thread, all the action, event, etc. listeners run in this thread. So if your code performs a long running/time consuming or blocking task in the EDT, then the Swing UI will become frozen until your code is done. In order to prevent this situation, there are other threads that your tasks can use: <ul> <li>You can leverage some worker threads that Swing itself creates so that background tasks can be performed outside of the EDT for long running/time consuming/blocking operations that your task must perform, or  <li>You can use threads that you explicitly create and then coordinate the output from these threads with the EDT, or  <li>You can take a blended approach and do both of the things suggested above. </li></ul> <p>In this tutorial, I will cover all three strategies for making your Swing apps multithreaded, with code examples, and things to keep in mind when designing such systems. <h3><a name="strategy1"></a>Strategy #1: Leverage Swing provided background threads (SwingWorker tasks) only</h3> <p><strong>Use case: </strong> <blockquote> <p>Perform a one-shot task, started from the user interface, that only needs to update the UI with the final result of the task. Use a Swing threadpool executor to perform this task (not the EDT).</p></blockquote> <p><strong>Diagram:</strong> <blockquote> <p><img alt="" src="http://developerlife.com/swingandwebservices/pic1.png"></p></blockquote> <p><strong>Notes: </strong> <ul> <li>You have to create a subclass of SwingWorker and launch it by calling <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#execute%28%29">execute()</a>; this will probably happen in an ActionListener in your Swing code. Calling execute() submits this SwingWorker task to the threadpool that Swing keeps for running background tasks. The execute() method returns immediately; so your calling thread (which may be the EDT itself) will continue.  <ul> <li>Put the code for the background task in <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#doInBackground%28%29">T doInBackground()</a>. This is the code that performs the time consuming one-shot task. If exceptions are generated here, they can be caught by a call to <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#get%28%29">T get()</a>, so can the return value. Once this method completes (on the background thread), done() will be called <strong>on the EDT</strong>. The return value is of type “&lt;T&gt;” – this is whatever class you decide to make the doInBackground() method return. “&lt;T&gt;” is the result type returned by this SwingWorker’s doInBackground and get methods. You can either implement this time consuming task in this method, or you can call an external web service, or other gateway or proxy class to request something.  <li>The <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#done%28%29">done()</a> method is called <strong>on the EDT</strong> when your doInBackground() method exits (by returning a value or throwing an exception). In the done() method, you can retrieve the thrown exception or return value by calling get(). In this method, you have to perform whatever GUI updates, or interactions that are necessary with the return value or exceptions generated by the call to get(). </li></ul> <li>In this case the thread is started by calling execute() on the SwingWorker task itself. This submits the task to a threadpool of background threads that Swing manages, and the task will be executed in one of these threads.  <li>Please make sure that the task is easily interruptible – there is no way to preemptively interrupt/stop a thread in Java, only cooperative cancellation is possible.  <ul> <li>So, if you are performing any wait operations (waiting on a lock or monitor) make sure to catch the InterruptedException and cancel out of the task.  <li>If you are performing blocking IO, make sure to catch IOException, to cancel out of it. The underlying stream that this task is blocking on has to be closed. Presumably, the object calling <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#cancel%28boolean%29">cancel(true)</a> on your SwingWorker task will also have to call <a href="http://java.sun.com/javase/6/docs/api/java/io/Closeable.html#close%28%29">close()</a> on the underlying Input/OutputStream in order for this to work. If you are unblocked due to to an IOException, you can always check for isCancelled() on the SwingWorker to see if it’s been cancelled.  <li>Also, make sure to check <a href="http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html#isCancelled%28%29">isCancelled()</a> on the SwingWorker thread to see if the task has been cancelled, to end your task.  <li>If you don’t know what to do with the InterruptedException (if one is thrown), and if you catch it, <strong>make sure to call </strong><a href="http://java.sun.com/javase/6/docs/api/java/lang/Thread.html#interrupt%28%29"><strong>Thread.currentThread().interrupt()</strong></a><strong> to maintain the interrupted flag,</strong> so that the <a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/executors.html">executor</a> running this thread will know what to do with the interruption. More on preserving thread interrupted state (if you don’t know what to do with the caught InterruptedException is explained <a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/interrupt.html">here</a>). </li></ul></li></ul> <h3><a name="strategy2"></a>Strategy #2: Create your own threads to perform one-shot tasks, and coordinate with SwingWorker tasks</h3> <p><strong>Use case:</strong> <blockquote> <p>Perform a one-shot task, started from the user interface (or not), that only needs to update the UI with the final result of the task. Use your own executor to perform the task (not the EDT, or a Swing threadpool executor).</p></blockquote> <p><strong>Diagram:</strong> <blockquote> <p><img alt="" src="http://developerlife.com/swingandwebservices/pic2.png"></p></blockquote> <p><strong>Notes:</strong> <ul> <li>The only differences between Strategy 1 and 2 are the following:  <ul> <li>In Strategy 2, instead of performing the time consuming task in the doInBackground(), you simply delegate this responsibility to another task being executed in a different executor (which has it’s own thread(s)). The reason for doing this is that you may have some multithreaded components/libraries/objects that you’ve created that are not tied to Swing. You may have a proxy class that acts as a gateway to an external web service. Instead of having to link this code to Swing’s SwingWorker, you can use a generic Executor or Callable or Runnable to implement this. Then you have the task of tying this underlying threaded component to a SwingWorker, basically by creating an SwingWorker adapter for your underlying threaded component. All the processing happens in your underlying component, and the results are trasmitted to the SwingWorker task. So how do you pass a return value in case your underlying component implements Runnable? If the underlying component implements Callable, and you have a reference to a Future, it’s easy – you can just call get() and wait in the doInBackground method of your adapter. However, if you don’t have an reference to a Future, and you are dealing with Runnable implementation, then you will have pass the results back to doInBackground’s thread via a BlockingQueue&lt;T&gt;. So your SwingWorker adapter will have to get a reference to this BlockingQueue&lt;T&gt; when it’s created, and then in the doInBackground method, it will wait until it gets an object of type &lt;T&gt; from this queue. Your underlying threaded component will have to pass the results of its computation via this BlockingQueue&lt;T&gt; as well. This is a contract that <strong>must </strong>be honored by both your SwingWorker adapter class, and the underlying threaded component, in order for this strategy to work.  <li>If your underlying component uses Callable, instead of Runnable, then there’s no need to use a BlockingQueue&lt;T&gt;. The doInBackground method of your SwingWorker adapter can simply call the get() method on the Future returned by the execution of the Callable. In this case, the blocking/waiting still happens in the doInBackground method, so that when everything is completed, done() is called on the EDT. In this scenario, Strategy 2 is very similar to Strategy 1, the only difference being that the doInBackground method doesn’t really implement anything, it just uses a Future to get a return value back from your underlying component (which is treaded). </li></ul> <li>The similarities between Strategy 1 and 2 are the following:  <ul> <li>You don’t really use publish or process methods (which you will in Strategy 3).  <li>The SwingWorker subclass is very similar, you have to declare a subclass in both cases like this: MySwingWorkerTask &lt;T, Void&gt; extends SwingWorker… </li></ul></li></ul> <h3><a name="strategy3"></a>Strategy #3: Create your own threads to perform recurring/long running tasks, and coordinate with SwingWorker tasks</h3> <p><strong>Use case: </strong> <blockquote> <p>Perform a long running or recurring task, started from the user interface (or not), that needs to update the UI with intermediate/periodic results from the task. No final result has to be returned by the task (this is optional). Use your own executor to perform this long running/recurring task (not the EDT, or a Swing threadpool executor).</p></blockquote> <p><strong>Diagram:</strong> <blockquote> <p><img alt="" src="http://developerlife.com/swingandwebservices/pic3.png"></p></blockquote> <p><strong>Notes:</strong> <ul> <li>The SwingWorker subclass is defined as SwingWorker&lt;Void, V&gt; : The reason the first parameter type is Void, is due to the fact that the final result returned by doInBackground is not important. However, unlike the previous strategies, the 2nd type parameters is &lt;V&gt; – this is the type of the intermediate values that are passed from the background thread to the EDT via publish -&gt; process.  <li>Once this SwingWorker task is started, it continually blocks on the BlockingQueue&lt;V&gt; object that the underlying threaded component uses to pass intermediate objects back to the SwingWorker adapter. The done() method isn’t used, and neither is get(); instead the publish() and process() methods are used in this strategy. As soon as an object is available on the BlockingQueue&lt;V&gt;, the SwingWorker task simply publishes that object. When objects are published, the EDT is notified of this, and it calls process() to get the objects that were published. Multiple calls to publish() are coalesed into one call to process() which is why the process method takes a List&lt;V&gt; chunks object as a parameter.  <li>The EDT actually runs the process method, so this is where you want to update your GUI and return. </li></ul> <p>Enjoy! <img src ="http://www.blogjava.net/cherishchen/aggbug/328310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-08-09 14:15 <a href="http://www.blogjava.net/cherishchen/archive/2010/08/09/328310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ComboBox Secret</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/23/326910.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Fri, 23 Jul 2010 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/23/326910.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326910.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/23/326910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326910.html</trackback:ping><description><![CDATA[<pre><code>comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE)</code></pre><pre><code></code>&nbsp;</pre><pre><code>Related question:</code></pre>
<p>Default when I press down or up key in combobox then popup list with items is show and when I move on this list (by keys) then items on list is selected and comnobox value is changed. Is there any way to keep this selection on the list, but remove auto combobox value changed ?</p><img src ="http://www.blogjava.net/cherishchen/aggbug/326910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-23 10:48 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/23/326910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>About GC and memory leak</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326014.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 12:51:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326014.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326014.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326014.html</trackback:ping><description><![CDATA[<h4><a href="http://chaoticjava.com/posts/gc-tips-and-memory-leaks/">GC Tips and Memory Leaks</a></h4> <h3><a href="http://blog.csdn.net/calvinxiu/archive/2007/05/22/1621051.aspx">编写对GC友好，又不泄漏的代码</a></h3> <h3><a href="http://olex.openlogic.com/wazi/2009/how-to-fix-memory-leaks-in-java/">How to Fix Memory Leaks in Java</a>(very good)</h3> <h3><a href="http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html">Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning</a></h3> <h3><a href="http://java.sun.com/javase/technologies/hotspot/gc/index.jsp">Java HotSpot Garbage Collection</a></h3> <p><a href="http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp">Java HotSpot VM Options</a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/326014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 20:51 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Understanding Weak References</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326013.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 12:47:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326013.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326013.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326013.html</trackback:ping><description><![CDATA[<p><a title="http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html" href="http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html">http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html</a></p><img src ="http://www.blogjava.net/cherishchen/aggbug/326013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 20:47 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据结构与算法-- Heap</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326012.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 12:41:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326012.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326012.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326012.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326012.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326012.html</trackback:ping><description><![CDATA[<div><pre><span style="color: #0000ff">import</span> java.util.Arrays;

<span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> HeapSortV3 {
	<span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span>[] heap = {4, 1, 3, 2, 16,9,10,14,8,7 }; 
	
	<span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> main(String[] args) {
		HeapSortV3 v = <span style="color: #0000ff">new</span> HeapSortV3();
		v.heapSort(heap, heap.length);
	}
	
	<span style="color: #008000">/**
	 * 
	 * @param a
	 * @param i, the indict of array, begin from 0
	 * @param n, the heap size
	 */</span>
	<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> heapify(<span style="color: #0000ff">int</span>[] a, <span style="color: #0000ff">int</span> i, <span style="color: #0000ff">int</span> n) {
		<span style="color: #0000ff">int</span> l = leftChild(i);
		<span style="color: #0000ff">int</span> r = leftChild(i) + 1;
		<span style="color: #0000ff">int</span> largest = -1;
		<span style="color: #0000ff">if</span>(l&lt; n &amp;&amp; a[l]&gt;a[i]) {
			largest = l;
		}<span style="color: #0000ff">else</span> {
			largest = i;
		}
		
		<span style="color: #0000ff">if</span>(r&lt; n &amp;&amp; a[r]&gt; a[largest]) {
			largest = r;
		}
		
		<span style="color: #008000">// if largest is not the current node, swap them, recurs to subtree</span>
		<span style="color: #0000ff">if</span>(largest!=i) {
			swap(a,largest,i);
			heapify(a, largest, n);
		}
	}

	
	<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> buildHeap(<span style="color: #0000ff">int</span>[] a, <span style="color: #0000ff">int</span> n) {
		<span style="color: #008000">// why begin from n/2?</span>
		<span style="color: #008000">// becuase for complete binary tree, n/2 is last non-leaf node,i.e, n/2+1,n/2+2 ...n are all leaf nodes.</span>
		<span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = n/2; i &gt;=0; i--) {
			heapify(a, i, n);
		}
	}
	
	<span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> leftChild(<span style="color: #0000ff">int</span> i) {
		<span style="color: #0000ff">return</span> 2*i + 1;
	}
	
	<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> heapSort(<span style="color: #0000ff">int</span>[] a,<span style="color: #0000ff">int</span> n) {
		buildHeap(a, n);
		System.out.println(Arrays.toString(a));
		<span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = n-1; i &gt;= 1; i--) {
			<span style="color: #008000">// swap 0 and i(n-1,n-2,...1)</span>
			swap(a, 0, i);
			<span style="color: #008000">// remove the last element, so heap size is i(n-1,n-2,n-3...1)</span>
			heapify(a, 0, i);
		}
		System.out.println(Arrays.toString(a));
	}
	
	<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> swap(<span style="color: #0000ff">int</span>[] source, <span style="color: #0000ff">int</span> dex1, <span style="color: #0000ff">int</span> dex2) {
		<span style="color: #0000ff">int</span> temp = source[dex1];
		source[dex1] = source[dex2];
		source[dex2] = temp;
	}
}</pre></div><img src ="http://www.blogjava.net/cherishchen/aggbug/326012.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 20:41 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326012.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 路径的获取</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326002.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 11:09:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326002.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326002.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326002.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326002.html</trackback:ping><description><![CDATA[<p>System.out.println(PreferenceUtil.class.getClassLoader().getResource(""));&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(ClassLoader.getSystemResource(""));&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(PreferenceUtil.class.getResource(""));&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(PreferenceUtil.class.getResource("/"));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Class文件所在路径<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(new File("/").getAbsolutePath());&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(System.getProperty("user.dir"));</p><img src ="http://www.blogjava.net/cherishchen/aggbug/326002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 19:09 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mysql high performance study</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326001.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 11:08:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326001.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326001.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326001.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326001.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326001.html</trackback:ping><description><![CDATA[<p>Oreilly high performance mysql 2rd edition</p> <h1>Architecture</h1> <p>MySQL’s most unusual and important feature is its storage-engine architecture, whose design separates query processing and other server tasks from data storage and retrieval.  <p>This separation of concerns lets you choose, on a per-table basis, how your data is stored and what performance, features, and other characteristics you want.  <p><a href="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/Mysqlhighperformancestudy_D787/image_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/Mysqlhighperformancestudy_D787/image_thumb.png" width="324" height="244"></a>  <p>Mysql的一个最显著的特征就是其存储引擎架构，这样不仅仅可以底层的数据存取从server中剥离，同时可以做到同一个数据库不同表采用不同的底层数据存储格式，以满足不同的性能以及应用的要求。  <p>&nbsp;</p> <p>The optimizer does not really care what storage engine a particular table uses, but the storage engine does affect how the server optimizes query. The optimizer asks the storage engine about some of its capabilities and the cost of certain operations, and for statistics on the table data.  <p>&nbsp;</p> <h2>Mysql 对transaction的支持</h2> <p>MySQL AB provides three transactional storage engines: InnoDB, NDB Cluster, and Falcon. </p> <p>MySQL doesn’t manage transactions at the server level. Instead, the underlying storage engines implement transactions themselves. This means you can’t reliably mix different engines in a single transaction. MySQL AB is working on adding a higher level transaction management service to the server, which will make it safe to mix and match transactional tables in a transaction.  <p>因为目前mysql是在storage engine层实现事务的支持，所以在一个事务中操作多个不同engine的表是不可靠的，要实现这个功能需要上层的server的支持。</p> <p>&nbsp;</p> <h2>Implicit and explicit locking</h2> <p><br>InnoDB uses a two-phase locking protocol. It can acquire locks at any time during a transaction, but it does not release them until a COMMIT or ROLLBACK. It releases all the locks at the same time. The locking mechanisms described earlier are all implicit. InnoDB handles locks automatically, according to your isolation level.  <p>However, InnoDB also supports explicit locking, which the SQL standard does not<br>mention at all:<br>•&nbsp; SELECT ... LOCK IN SHARE MODE<br>•&nbsp; SELECT ... FOR UPDATE  <p>&nbsp;</p> <h2>MySQL’s Storage Engines</h2> <p>&nbsp;<a href="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/Mysqlhighperformancestudy_D787/image_4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.blogjava.net/images/blogjava_net/cherishchen/WindowsLiveWriter/Mysqlhighperformancestudy_D787/image_thumb_1.png" width="948" height="482"></a> </p> <h3>Storage Engine Considerations</h3><br> <p>Here are the main elements you should take into account:</p> <ul> <li><strong>Transactions<br></strong>If&nbsp; your&nbsp; application&nbsp; requires&nbsp; transactions,&nbsp; InnoDB&nbsp; is&nbsp; the&nbsp; most&nbsp; stable,&nbsp; well integrated, proven choice. <br>MyISAM is a good choice if a task doesn’t require transactions and issues primarily either SELECT or INSERT queries. Sometimes specific components of an application (such as logging) fall into this category.</li></ul> <p>&nbsp;</p> <ul> <li><strong>Concurrency</strong><br>How best to satisfy your concurrency requirements depends on your workload.If you just need to insert and read concurrently, believe it or not, MyISAM is a fine choice! If you need to allow a mixture of operations to run concurrently without interfering with each other, one of the engines with row-level locking should work well.</li></ul> <p>&nbsp;</p> <ul> <li><strong>Backups</strong><br>The need to perform regular backups may also influence your table choices. If your&nbsp; server&nbsp; can&nbsp; be&nbsp; shut&nbsp; down&nbsp; at&nbsp; regular&nbsp; intervals&nbsp; for&nbsp; backups,&nbsp; the&nbsp; storage engines are equally easy to deal with. However, if you need to perform online backups in one form or another, the choices become less clear. Also bear in mind that using multiple storage engines increases the complexity of backups and server tuning.</li></ul> <p>&nbsp;</p> <ul> <li><strong>Crash recovery</strong></li></ul> <blockquote> <p>If you have a lot of data, you should seriously consider how long it will take to recover from a crash. MyISAM tables generally become corrupt more easily and take much longer to recover than InnoDB tables, for example. In fact, this is one of the most important reasons why a lot of people use InnoDB when they don’t need transactions.</p></blockquote> <p>更改storage engine</p> <ul> <li>&nbsp;<strong>Alter table</strong> 语句：</li></ul> <blockquote> <p>mysql&gt; ALTER TABLE mytable ENGINE = Falcon;</p> <p>缺点是速度比较慢，MySQL will perform a row-by-row copy of your old table into a new table.&nbsp; During that time, you’ll probably be using all of the server’s disk I/O capacity, and the original table will be read-locked while the conversion runs. </p></blockquote> <ul> <li><strong>Dump and import</strong>： </li></ul> <blockquote> <p>Once you’ve dumped the table, you can simply edit the dump file to adjust the CREATE TABLE statement it contains. Be sure to change the table name as well as its type, because you can’t have two tables with the same name in the same database even if they are of different types—and mysqldump defaults to writing a DROP TABLE command before the CREATE TABLE, so you might lose your data if you are not careful!</p></blockquote> <ul> <li><strong>CREATE and SELECT</strong></li></ul> <blockquote> <p>mysql&gt; CREATE TABLE innodb_table <strong>LIKE</strong> myisam_table;<br>mysql&gt; ALTER TABLE innodb_table ENGINE=InnoDB;<br>mysql&gt; INSERT INTO innodb_table SELECT * FROM myisam_table;</p></blockquote> <blockquote> <p>这种方式最安全，毕竟如果源表存在大量的数据，最好采用增量插入和提交的方式，以加快速度。方法如下：</p> <p>mysql&gt; START TRANSACTION;<br>mysql&gt; INSERT INTO innodb_table SELECT * FROM myisam_table<br>&nbsp;&nbsp;&nbsp; -&gt; WHERE id BETWEEN x AND y;<br>mysql&gt; COMMIT;</p></blockquote> <h1>Benchmarking and Profiling</h1> <h3>Performance Measurements</h3> <ul> <li><strong>Transactions per time unit or throughput</strong></li></ul> <blockquote> <p>The usual unit of measurement is transactions per second.</p></blockquote> <ul> <li><strong>Response time or latency</strong></li></ul> <blockquote> <p>Maximum response time is rarely a useful metric, because the longer the bench-mark runs, the longer the maximum response time is likely to be. It’s also not at all repeatable, as it’s likely to vary widely between runs. For this reason, many people use percentile response times instead. For example, if the 95th percentile response time is 5 milliseconds, you know that the task finishes in less than 5 milliseconds 95% of the time.</p></blockquote> <ul> <li><strong>Scalability</strong></li></ul> <blockquote> <p>Scalability measurements are useful for systems that need to maintain performance under a changing workload.<br>“Performance under a changing workload” is a fairly abstract concept. Performance is typically measured by a metric such as throughput or response time, and the workload may vary along with changes in database size, number of con-current connections, or hardware.<br>Scalability measurements are good for capacity planning, because they can show weaknesses in your application that other benchmark strategies won’t show.</p></blockquote> <ul> <li><strong>Concurrency</strong></li></ul> <p>&nbsp;</p> <h3>Benchmarking Tools</h3> <p>Full-Stack Tools:ab,http_load,jmeter</p> <p>Single-Component Tools: mysqlslap,sysbench,Database Test Suite,MySQL Benchmark Suite (sql-bench),Super Smack</p> <p>&nbsp;</p> <h3>MySQL Profiling</h3> <ul> <li>Which data MySQL accesses most  <li>What kinds of queries MySQL executes most  <li>What states MySQL threads spend the most time in  <li>What subsystems MySQL uses most to execute a query  <li>What kinds of data accesses MySQL does during a query  <li>How much of various kinds of activities, such as index scans, MySQL does</li></ul> <p>&nbsp;</p> <p>MySQL has two kinds of query logs: the general log and the slow log.</p> <p>The general log writes out every query as the server receives it, so it contains queries that may not even be executed due to errors. You can enable it with a single configuration directive:<br>log = &lt;file_name&gt;</p> <p><br>By design, the general log does not contain execution times or any other information that’s available only after a query finishes. In contrast, the <strong>slow log contains only queries that have executed</strong>, <strong>it logs queries that take more than a specified amount of time to execute</strong>. Both logs can be helpful for profiling, <strong>but the slow log&nbsp; is&nbsp; the&nbsp; primary&nbsp; tool&nbsp; for&nbsp; catching&nbsp; problematic&nbsp; queries</strong>.&nbsp; We&nbsp; usually&nbsp; recommend<br>enabling it.</p> <p><br>The following configuration sample will enable the log, capture all queries that take more than <strong>two seconds</strong> to execute, and log queries that don’t use any indexes. It will also log slow administrative statements, such as OPTIMIZE TABLE:<br></p> <p>log-slow-queries&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &lt;file_name&gt;<br>long_query_time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 2<br><strong>log-queries-not-using-indexes<br>log-slow-admin-statements</strong></p> <p>You should customize this sample and place it in your <strong>my.cnf</strong> server configuration file. </p> <p><br>In MySQL 5.1, the global slow_query_log and slow_query_log_file system variables provide runtime control over the slow query log, but in MySQL 5.0, you can’t turn the&nbsp; slow&nbsp; query&nbsp; log&nbsp; on&nbsp; or&nbsp; off&nbsp; without&nbsp; restarting&nbsp; the&nbsp; MySQL&nbsp; server.&nbsp; The&nbsp; usual workaround for MySQL 5.0 is the long_query_time variable, which you can change dynamically. The following command doesn’t really disable slow query logging, but it has practically the same effect (if any of your queries takes longer than 10,000 seconds to execute, you should optimize it anyway!):</p> <p><br>mysql&gt; SET GLOBAL long_query_time = 10000;</p> <p><br>A related configuration variable, <strong>log_queries_not_using_indexes</strong>, makes the server log to the slow log any queries that don’t use indexes, no matter how quickly theyexecute. Although enabling the slow log normally adds only a small amount of log-ging overhead relative to the time it takes a “slow” query to execute, queries that don’t use indexes can be frequent and very fast (for example, scans of very small tables). Thus, logging them can cause the server to slow down, and even use a lot of disk space for the log.</p> <p><br><strong>Unfortunately, you can’t enable or disable logging of these queries with a dynamically settable variable in MySQL 5.0. You have to edit the configuration file, then restart MySQL.</strong> One way to reduce the burden without a restart is to make the log file a symbolic link to /dev/null when you want to disable it (in fact, you can use this trick for any log file). You just need to run FLUSH LOGS after making the change to ensure that MySQL closes its current log file descriptor and reopens the log to /dev/null.<br></p> <p>In contrast to MySQL 5.0, MySQL 5.1 lets you change logging at runtime and lets you log to tables you can query with SQL. This is a great improvement.</p> <p>Note:The minimum value for long_query_time in MySQL 5.0 is one second,for most interactive applications, this is way too long.</p> <p>Slow log是有一系列不足的，包括最小单位是太大（1秒），不能log slave thread query</p> <p><a title="http://www.mysqlperformanceblog.com/mysql-patches/" href="http://www.mysqlperformanceblog.com/mysql-patches/">http://www.mysqlperformanceblog.com/mysql-patches/</a> 提供了一个补丁，可以弥补上述不足</p> <p>When profiling, it’s a good idea to log all queries with long_query_time=0</p> <p>&nbsp;</p> <p>Appearing in the log simply means the query took a long time then; it doesn’t mean it will take a long time now or in the future. There<br>are many reasons why a query can be slow sometimes and fast at other times: <br>•&nbsp; A table may have been locked, causing the query to wait. The Lock_time indi-cates how long the query waited for locks to be released.<br>•&nbsp; The data or indexes may not have been cached in memory yet. This is common when MySQL is first started or hasn’t been well tuned.<br>•&nbsp; A nightly backup process may have been running, making all disk I/O slower.<br>•&nbsp; The server may have been running other queries at the same time, slowing down this query.</p> <p><br>As a result, you should view the slow query log as only a partial record of what’s happened. You can use it to generate a list of possible suspects, but you need to investigate each of them in more depth.<br>The slow query log patches are specifically designed to try to help you understand why a query is slow. In particular, if you’re using InnoDB, the InnoDB statistics can help a lot: you can see if the query was waiting for I/O from the disk, whether it had to spend a lot of time waiting in the InnoDB queue, and so on.</p> <p>&nbsp;</p> <h3>Log analysis tools:mysqldumpslow,mysql_slow_log_filter,mysql_slow_log_parser,mysqlsla</h3> <p><br>&nbsp; <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p><font size="4">In general, MySQL can apply a WHERE clause in three ways, from best to worst:<br>•&nbsp; Apply the conditions to the index lookup operation to eliminate nonmatching rows. This happens at the storage engine layer.<br>•&nbsp; Use a covering index<font color="#800000"> (“Using index” in the Extra column)</font> to avoid row accesses, and filter out nonmatching rows after retrieving each result from the index. </font><font size="4"><font color="#ff0000">This happens at the <em>server layer,</em> but it doesn’t require reading rows from the table.<br></font>•&nbsp; Retrieve rows from the table, then filter nonmatching rows <font color="#ff0000">(“Using where” in the Extra column).</font> <font color="#ff0000">This happens at the<em> server layer</em> and requires the server to read rows from the table before it can filter them.</font></font>  <p><font color="#ff0000" size="4"></font>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <ol> <li>一条 SQL 语句只能使用 1 个索引 (5.0-)，MySQL 根据表的状态，选择一个它认为最好的索引用于优化查询  <li>联合索引，只能按从左到右的顺序依次使用 </li></ol> <p>&nbsp;</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>总结一下：&nbsp; <br>&nbsp;&nbsp; 1.一般有order by语句，在索引加得不当的情况下，都有可能出现Using filesort，这时候就要对SQL语句和索引进行优化了，但是，并不是说出现Using filesort就是个严重的问题，不是这样的，此次举的例子比较极端，几乎不太可能出现这么傻瓜的查询，优化和不优化，要看它是不是影响了业务性能。<br>&nbsp;&nbsp; 2. 从上面可以看到联合索引，也可以叫多列索引，形如 key ('A1','A2','A3' ,'A4')等的，排序的思路一般是，先按照A1来排序，A1相同，然后按照A2排序，以此类推，这样对于（A1）,(A1,A2), (A1,A2,A3)的索引都是有效的，但是对于（A2,A3）这样的索引就无效了。  <img src ="http://www.blogjava.net/cherishchen/aggbug/326001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 19:08 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java NIO</title><link>http://www.blogjava.net/cherishchen/archive/2010/07/13/326000.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Tue, 13 Jul 2010 11:07:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/07/13/326000.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/326000.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/07/13/326000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/326000.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/326000.html</trackback:ping><description><![CDATA[<p><a title="http://java.sun.com/jsp_utils/PrintPage.jsp?url=http%3A%2F%2Fjava.sun.com%2Fdeveloper%2FtechnicalArticles%2Freleases%2Fnio%2F" href="http://java.sun.com/jsp_utils/PrintPage.jsp?url=http%3A%2F%2Fjava.sun.com%2Fdeveloper%2FtechnicalArticles%2Freleases%2Fnio%2F">http://java.sun.com/jsp_utils/PrintPage.jsp?url=http%3A%2F%2Fjava.sun.com%2Fdeveloper%2FtechnicalArticles%2Freleases%2Fnio%2F</a>  <p>Back in January 2000, while many people were arguing about whether the year 2000 was the last or first year of the century, life began for JSR 51 as an approved Java Specification Request (JSR). The name of that JSR is <strong>New I/O APIs for the Java Platform</strong>. Many people think of the new capabilities as just offering non-blocking I/O operations. However, the new features introduced into the Java<sup>TM</sup><sup></sup> 2 Platform, Standard Edition (J2SE<sup>TM</sup><sup></sup>), version 1.4 Beta, include many other new and interesting features. While the API certainly will offer support for scalable I/O operations for both sockets and files, you'll also find a regular expression package for pattern matching, encoders and decoders for character set conversions, and improved file system support like file locking and memory mapping. All four of these new features will be covered in this article.  <p>Note: The Java Native Interface (JNI) changes made to support the New I/O operations will not be covered. For information on these changes, see the <a href="http://java.sun.com/developer/technicalArticles/releases/nio/#Resources">Resources</a> section at the end of this article.  <h2>Buffers</h2> <p>Starting from the simplest and building up to the most complex, the first improvement to mention is the set of <code>Buffer</code> classes found in the <code>java.nio</code> package. These buffers provide a mechanism to store a set of primitive data elements in an in-memory container. Basically, imagine wrapping a combined <code>DataInputStream</code>/<code>DataOutputStream</code> around a fixed-size byte array and then only being able to read and write one data type, like <code>char</code>, <code>int</code>, or <code>double</code>. There are seven such buffers available:  <ul> <li><code>ByteBuffer</code>  <li><code>CharBuffer</code>  <li><code>DoubleBuffer</code>  <li><code>FloatBuffer</code>  <li><code>IntBuffer</code>  <li><code>LongBuffer</code>  <li><code>ShortBuffer</code></li></ul> <p>The <code>ByteBuffer</code> actually supports reading and writing the other six types, but the others are type specific. To demonstrate the use of a buffer, the following snippet converts a <code>String</code> to a <code>CharBuffer</code> and reads a character at a time. You convert the <code>String</code> to a <code>CharBuffer</code> with the <code>wrap</code> method, then get each letter with the <code>get</code> method. <pre>CharBuffer buff = CharBuffer.wrap(args[0]);
for (int i=0, n=buff.length(); i&lt;n; i++) {
  System.out.println(buff.get());
}
</pre>
<p>When using buffers, it is important to realize there are different sizing and positioning values to worry about. <strong>The <code>length</code> method is actually non-standard, specific to <code>CharBuffer</code>. There is nothing wrong with it, but it really reports the <em>remaining</em> length, so if the position is not at the beginning, the reported length will not be the buffer length, but the number of remaining characters within the buffer.</strong> In other words, the above loop can also be written as follows. <pre>CharBuffer buff = CharBuffer.wrap(args[0]);
for (int i=0; <strong>buff.length() &gt; 0</strong>; i++) {
  System.out.println(buff.get());
}
</pre>
<p><strong>Getting back to the different sizing and positioning values, the four values are known as mark, position, limit, and capacity: </strong>
<ul>
<li><strong>mark -- setable position with <code>mark</code> method that can be used to reset the position with <code>reset</code>, &lt;= position, &gt;= 0 </strong>
<li><strong>position -- <font color="#ff0000">current</font> read/write position within buffer, &lt;= limit ，类似于活动游标，一般应该作为读或者写的下限</strong> 
<li><strong>limit -- index of first element that should not be read, &lt;= capacity 读写的上限</strong> 
<li><strong>capacity -- size of buffer, &gt;= limit </strong></li></ul>
<p><strong>The position is an important piece of information to keep in mind when reading from and writing to a buffer. For instance, if you want to read what you just wrote you must move the position to where you want to read from, otherwise, you'll read past the limit and get whatever just happens to be there</strong>. This is where the <code>flip</code> method comes in handy, changing the limit to the current position and moving the current position to zero. You can also <code>rewind</code> a buffer to keep the current limit and move the position back to zero. For example, removing the <code>flip</code> call from the following snippet will get back a space, assuming nothing was put in the buffer originally. <pre>buff.put('a');
buff.flip();
buff.get();
</pre>
<p>flip: changing the limit to the current position and moving the current position to zero 
<p>rewind:keep the current limit and move the position back to zero 
<p>&nbsp; <p>The <code>wrap</code> mechanism shown above is an example of a non-direct buffer. Non-direct buffers can also be created and sized with the <code>allocate</code> method, essentially wrapping the data into an array. At a slightly higher creation cost, you can also create a contiguous memory block, also called a <i>direct</i> buffer, with the <code>allocateDirect</code> method. <strong>Direct buffers rely on the system's native I/O operations to optimize access operations. </strong>
<h2>Mapped Files</h2>
<p>There is one specialized form of direct <code>ByteBuffer</code> known as a <code>MappedByteBuffer</code>. This class represents a buffer of bytes mapped to a file. To map a file to a <code>MappedByteBuffer</code>, you first must get the channel for a file. <strong>A <i>channel</i> represents a connection to something</strong>, such as a pipe, socket, or file, that can perform I/O operations. In the case of a <code>FileChannel</code>, you can get one from a <code>FileInputStream</code>, <code>FileOutputStream</code>, or <code>RandomAccessFile</code> through the <code>getChannel</code> method. Once you have the channel, you map it to a buffer with <code>map</code>, specifying the mode and portion of the file you want to map. The file channel can be opened with one of the <code>FileChannel.MapMode</code> constants: read-only (<code>READ_ONLY</code>), private/copy-on-write (<code>PRIVATE</code>), or read-write (<code>READ_WRITE</code>). 
<p>Here's the basic process for creating a read-only <code>MappedByteBuffer</code> from a file: <pre>String filename = ...;
FileInputStream input = new FileInputStream(filename);
FileChannel channel = input.getChannel();
int fileLength = (int)channel.size();
MappedByteBuffer buffer =  channel.map(FileChannel.MapMode.READ_ONLY, 0, fileLength);
</pre>
<p>You'll find the channel-related classes in the <code>java.nio.channels</code> package. 
<p>Once the <code>MappedByteBuffer</code> has been created, you can access it like any other <code>ByteBuffer</code>. In this particular case though, it is read-only, so any attempt to <code>put</code> something will throw an exception, <code>NonWritableChannelException</code> in this case. If you need to treat the bytes as characters, you must convert the <code>ByteBuffer</code> into a <code>CharBuffer</code> through the use of a character set for the conversion. This character set is specified by the <code>Charset</code> class. You then decode the file contents through the <code>CharsetDecoder</code> class. There is also a <code>CharsetEncoder</code> to go in the other direction. <pre>// ISO-8859-1  is ISO Latin Alphabet #1
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
</pre>
<p>These classes are found in the <code>java.nio.charset</code> package. 
<h2>Regular Expressions</h2>
<p>Once you've mapped the input file to a <code>CharBuffer</code>, you can do pattern matching on the file contents. Think of running <code>grep</code> or <code>wc</code> on the file to do regular expression matching or word counting, respectively. That's where the <code>java.util.regex</code> package comes into play and the <code>Pattern</code> and <code>Matcher</code> classes get used. 
<p>The <code>Pattern</code> class provides a whole slew of constructs for matching regular expressions. Basically, you provide the pattern as a <code>String</code>. See the class documentation for full details of the patterns. Here are some samples to get you started: 
<ul>
<li>Line pattern, any number of characters followed by carriage return and/or line feed: .*\r?\n or .*$ 
<li>Series of numbers: [0-9]* or \d* 
<li>A control character {cntrl} 
<li>An upper or lowercase US-ASCII character, followed by white space, followed by punctuation: [\p{Lower}\p{Upper}]\s\p{Punct} </li></ul>
<p>Note: Unfortunately, the beta 3 version of J2SE 1.4 broke just about everything that deals with character sequence views of character buffers (which are necessary for regular expressions). See <a href="http://developer.java.sun.com/developer/bugParade/bugs/4510323.html">Bug Parade</a> for a description of the problem. Unfortunately, that means that you can't use the pattern matcher to read a word/line at a time. 
<p>For additional information about the regular expression library, see the <em>Regular Expressions and the Java Programming Language</em> article referenced in the <a href="http://java.sun.com/developer/technicalArticles/releases/nio/#Resources">Resources</a>. 
<h2>Socket Channels</h2>
<p>Moving on from file channels takes us to channels for reading from and writing to socket connections. These channels can be used in a blocking or non-blocking fashion. In the blocking fashion, they just replace the call to <code>connect</code> or <code>accept</code>, depending on whether you are a client or a server. In the non-blocking fashion, there is no equivalent. 
<p>The new classes to deal with for basic socket reading and writing are the <code>InetSocketAddress</code> class in the <code>java.net</code> package to specify where to connect to, and the <code>SocketChannel</code> class in the <code>java.nio.channels</code> package to do the actual reading and writing operations. 
<p>Connecting with <code>InetSocketAddress</code> is very similar to working with the <code>Socket</code> class. All you have to do is provide the host and port: <pre>String host = ...;
InetSocketAddress socketAddress = new  InetSocketAddress(host, 80);
</pre>
<p>Once you have the <code>InetSocketAddress</code>, that's where life changes. Instead of reading from the socket's input stream and writing to the output stream, you need to open a <code>SocketChannel</code> and connect it to the <code>InetSocketAddress</code>: <pre>SocketChannel channel = SocketChannel.open();
channel.connect(socketAddress);
</pre>
<p>Once connected, you can read from or write to the channel with <code>ByteBuffer</code> objects. For instance, you can wrap a <code>String</code> in a <code>CharBuffer</code> with the help of an <code>CharsetEncoder</code> to send an HTTP request: <pre>Charset charset = Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();
String request = "GET / \r\n\r\n";
channel.write(encoder.encode(CharBuffer.wrap(request)));
</pre>
<p>You can then read the response from the channel. Since the response for this HTTP request will be text, you'll need to convert that response into a <code>CharBuffer</code> through a <code>CharsetDecoder</code>. By creating just a <code>CharBuffer</code> to start, you can keep reusing the object to avoid unnecessary garbage collection between reads: <pre>ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);
while ((channel.read(buffer)) != -1) {
  buffer.flip();
  decoder.decode(buffer, charBuffer, false);
  charBuffer.flip();
  System.out.println(charBuffer);
  buffer.clear();
  charBuffer.clear();
}
</pre>
<p>The following program connects all these pieces to read the main page of a Web site through an HTTP request. Feel free to save the output to a file to compare the results to viewing the page with a browser. <a name="code1"></a><pre>import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;


public class ReadURL {
  public static void main(String args[]) {
    String host = args[0];
    SocketChannel channel = null;

    try {

      // Setup
      InetSocketAddress socketAddress = 
        new InetSocketAddress(host, 80);
      Charset charset = 
        Charset.forName("ISO-8859-1");
      CharsetDecoder decoder = 
        charset.newDecoder();
      CharsetEncoder encoder = 
        charset.newEncoder();

      // Allocate buffers
      ByteBuffer buffer = 
        ByteBuffer.allocateDirect(1024);
      CharBuffer charBuffer = 
        CharBuffer.allocate(1024);

      // Connect
      channel = SocketChannel.open();
      channel.connect(socketAddress);

      // Send request
      String request = "GET / \r\n\r\n";
      channel.write(encoder.encode(CharBuffer.wrap(request)));

      // Read response
      while ((channel.read(buffer)) != -1) {
        buffer.flip();
        // Decode buffer
        decoder.decode(buffer, charBuffer, false);
        // Display
        charBuffer.flip();
        System.out.println(charBuffer);
        buffer.clear();
        charBuffer.clear();
      }
    } catch (UnknownHostException e) {
      System.err.println(e);
    } catch (IOException e) {
      System.err.println(e);
    } finally {
      if (channel != null) {
        try {
          channel.close();
        } catch (IOException ignored) {
        }
      }
    }
  }
}
</pre>
<h2>Non-Blocking Reads</h2>
<p>Now comes the interesting part, and what people are most interested in in the new I/O packages. How do you configure the channel connection to non-blocking? The basic step is to call the <code>configureBlocking</code> method on the opened <code>SocketChannel</code>, and pass in a value of <code>false</code>. Once you call the <code>connect</code> method, the method now returns immediately. <pre>String host = ...;
InetSocketAddress socketAddress = 
  new InetSocketAddress(host, 80);
channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(socketAddress);
</pre>
<p>Once you have a non-blocking channel, you then have to figure out how to actually work with the channel. The <code>SocketChannel</code> is an example of a <code>SelectableChannel</code>. These selectable channels work with a <code>Selector</code>. Basically, you register the channel with the <code>Selector</code>, tell the <code>Selector</code> what events you are interested in, and it notifies you when something interesting happens. 
<p>To get a <code>Selector</code> instance, just call the static <code>open</code> method of the class: <pre>Selector selector = Selector.open();
</pre>
<p>Registering with the <code>Selector</code> is done through the <code>register</code> method of the channel. The events are specified by fields of the <code>SelectionKey</code> class. In the case of the <code>SocketChannel</code> class, the available operations are <code>OP_CONNECT</code>, <code>OP_READ</code>, and <code>OP_WRITE</code>. So, if you were interested in read and connection operations, you would register as follows: <pre>channel.register(selector, 
  SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
</pre>
<p>At this point, you have to wait on the selector to tell you when events of interest happen on registered channels. The <code>select</code> method of the <code>Selector</code> will block until something interesting happens. To find this out, you can put a <code>while (selector.select() &gt; 0)</code> loop in its own thread and then go off and do your own thing while the I/O events are being processed. The <code>select</code> method returns when something happens, where the value returned is the count of channels ready to be acted upon. This value doesn't really matter though. 
<p>Once something interesting happens, you have to figure out what happened and respond accordingly. For the channel registered here with the selector, you expressed interest in both the <code>OP_CONNECT</code> and <code>OP_READ</code> operations, so you know it can only be one of those events. So, what you do is get the <code>Set</code> of ready objects through the <code>selectedKeys</code> method, and iterate. The element in the <code>Set</code> is a <code>SelectionKey</code>, and you can check if it <code>isConnectable</code> or <code>isReadable</code> for the two states of interest. 
<p>Here's the basic framework of the loop so far: <pre>while (selector.select(500) &gt; 0) {
  // Get set of ready objects
  Set readyKeys = selector.selectedKeys();
  Iterator readyItor = readyKeys.iterator();

  // Walk through set
  while (readyItor.hasNext()) {

    // Get key from set
    SelectionKey key = 
      (SelectionKey)readyItor.next();

    // Remove current entry
    readyItor.remove();

    // Get channel
    SocketChannel keyChannel = 
      (SocketChannel)key.channel();

    if (key.isConnectable()) {

    } else if (key.isReadable()) {

    }
  }
}
</pre>
<p>The <code>remove</code> method call requires a little explanation. The ready set of channels can change while you are processing them. So, you should remove the one you are processing when you process it. Removal does not trigger a <code>ConcurrentModificationException</code> to be thrown. There's also a timeout setup here for the <code>select</code> call so it doesn't wait forever if there is nothing to do. There's also a call to get the channel from the key in there. You'll need that for each operation. 
<p>For the sample program here you're doing the equivalent of reading from an HTTP connection, so upon connection you need to send the initial HTTP request. Basically, once you know the connection is made, you send a GET request for the root of the site. When the selector reports that the channel is connectable, it may not have finished connecting yet. So, you should always check if the connection is pending through <code>isConnectionPending</code> and call <code>finishConnect</code> if it is. Once connected, you can write to the channel, but must use a <code>ByteBuffer</code>, not the more familiar I/O streams. 
<p>Here's what the connection code looks like: <pre>// OUTSIDE WHILE LOOP
Charset charset = 
     Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();

// INSIDE if (channel.isConnectable())
// Finish connection
if (keyChannel.isConnectionPending()) {
  keyChannel.finishConnect();
}

// Send request
String request = "GET / \r\n\r\n";
keyChannel.write
     (encoder.encode(CharBuffer.wrap(request)));
</pre>
<p>The reading from a socket channel is just like from a file channel. There is one exception though. It is more likely that the buffer may not be full when reading from a socket. Not a big deal though, as you are just going to read what is ready. <pre>// OUTSIDE WHILE LOOP
CharsetDecoder decoder = charset.newDecoder();
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
CharBuffer charBuffer = CharBuffer.allocate(1024);

// INSIDE if (channel.isReadable())
// Read what's ready in response
keyChannel.read(buffer);
buffer.flip();

// Decode buffer
decoder.decode(buffer, charBuffer, false);

// Display
charBuffer.flip();
System.out.print(charBuffer);

// Clear for next pass
buffer.clear();
charBuffer.clear();
</pre>
<p>Add in the necessary exception handling code and you have your socket reader. Be sure to <code>close</code> the channel in the <code>finally</code> clause to make sure its resources are released, even if there is an exception. Here's the complete client code: <a name="code2"></a><pre>import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;


public class NonBlockingReadURL {
  static Selector selector;

  public static void main(String args[]) {
    String host = args[0];
    SocketChannel channel = null;

    try {

      // Setup
      InetSocketAddress socketAddress = 
        new InetSocketAddress(host, 80);
      Charset charset = 
        Charset.forName("ISO-8859-1");
      CharsetDecoder decoder = 
        charset.newDecoder();
      CharsetEncoder encoder = 
        charset.newEncoder();

      // Allocate buffers
      ByteBuffer buffer = 
        ByteBuffer.allocateDirect(1024);
      CharBuffer charBuffer = 
        CharBuffer.allocate(1024);

      // Connect
      channel = SocketChannel.open();
      channel.configureBlocking(false);
      channel.connect(socketAddress);

      // Open Selector
      selector = Selector.open();

      // Register interest in when connection
      channel.register(selector, 
        SelectionKey.OP_CONNECT | 
          SelectionKey.OP_READ);

      // Wait for something of interest to happen
      while (selector.select(500) &gt; 0) {
        // Get set of ready objects
        Set readyKeys = selector.selectedKeys();
        Iterator readyItor = readyKeys.iterator();

        // Walk through set
        while (readyItor.hasNext()) {

          // Get key from set
          SelectionKey key = 
            (SelectionKey)readyItor.next();

          // Remove current entry
          readyItor.remove();

          // Get channel
          SocketChannel keyChannel = 
            (SocketChannel)key.channel();

          if (key.isConnectable()) {

            // Finish connection
            if (keyChannel.isConnectionPending()) {
              keyChannel.finishConnect();
            }

            // Send request
            String request = 
                 "GET / \r\n\r\n";
            keyChannel.write(encoder.encode(
              CharBuffer.wrap(request)));

          } else if (key.isReadable()) {

            // Read what's ready in response
            keyChannel.read(buffer);
            buffer.flip();

            // Decode buffer
            decoder.decode(buffer, 
              charBuffer, false);

            // Display
            charBuffer.flip();
            System.out.print(charBuffer);

            // Clear for next pass
            buffer.clear();
            charBuffer.clear();

          } else {
            System.err.println("Ooops");
          }
        }
      }
    } catch (UnknownHostException e) {
      System.err.println(e);
    } catch (IOException e) {
      System.err.println(e);
    } finally {
      if (channel != null) {
        try {
          channel.close();
        } catch (IOException ignored) {
        }
      }
    }
    System.out.println();
  }
}
</pre>
<h2>Non-Blocking Servers</h2>
<p>The final piece is having a Web server use the NIO package. With the new I/O capabilities, you can create a Web server that does <strong>not</strong> require one thread per connection. You can certainly pool threads for long processing tasks, but all you have to do is <code>select</code> and wait for something to do, not have all the threads waiting separately. 
<p>The basic setup of the server using channels involves you calling <code>bind</code> to connect a <code>ServerSocketChannel</code> to a <code>InetSocketAddress</code>. <pre>ServerSocketChannel channel = 
  ServerSocketChannel.open();
channel.configureBlocking(false);
InetSocketAddress isa = 
  new InetSocketAddress(port);
channel.socket().bind(isa);
</pre>
<p>Everything else is nearly the same as the client reading, except this time you need to register the <code>OP_ACCEPT</code> key, check for <code>isAcceptable</code> when the selector notifies you of the event, and get a <code>ServerSocketChannel</code> instead of a <code>SocketChannel</code>. It is that simple. 
<p>The following code example shows just how simple this is. It is your basic single-threaded server, sending back a canned text message for each request. Just use <code>telnet</code> to connect to port 9999 and see the response. <a name="code3"></a><pre>import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;

public class Server {
   private static int port = 9999;
   public static void main(String args[]) 
     throws Exception {
     Selector selector = Selector.open();

     ServerSocketChannel channel = 
       ServerSocketChannel.open();
     channel.configureBlocking(false);
     InetSocketAddress isa = new InetSocketAddress(port);
     channel.socket().bind(isa);

     // Register interest in when connection
     channel.register(selector, SelectionKey.OP_ACCEPT);

     // Wait for something of interest to happen
     while (selector.select() &gt; 0) {
       // Get set of ready objects
       Set readyKeys = selector.selectedKeys();
       Iterator readyItor = readyKeys.iterator();

       // Walk through set
       while (readyItor.hasNext()) {

         // Get key from set
         SelectionKey key = 
           (SelectionKey)readyItor.next();

         // Remove current entry
         readyItor.remove();

         if (key.isAcceptable()) {
           // Get channel
           ServerSocketChannel keyChannel =
             (ServerSocketChannel)key.channel();

           // Get server socket
           ServerSocket serverSocket = keyChannel.socket();

           // Accept request
           Socket socket = serverSocket.accept();

           // Return canned message
           PrintWriter out = new PrintWriter
             (socket.getOutputStream(), true);
           out.println("Hello, NIO");
           out.close();
         } else {
           System.err.println("Ooops");
         }

       }
     }
     // Never ends
   }
}
</pre>
<p>After accepting the request, you could get the channel from the socket, make it non-blocking, and register that with the selector, too. This framework just provides the basics of using the NIO classes within a Web server. For additional information about creating a multi-threaded server, see the JavaWorld article referenced in the <a href="http://java.sun.com/developer/technicalArticles/releases/nio/#Resources">Resources</a> section. 
<h2>Conclusion</h2>
<p>The New I/O features introduced to the J2SE version 1.4 Beta release provide exciting new ways to improve the performance of your programs. By taking advantage of the new capabilities, not only will they be faster but they can be much more scalable because you won't have to worry about tasks like one thread per connection. This is especially important on the server side, greatly increasing the possible number of simultaneous connections supported. 
<p>Note: If you look at the list of capabilities in JSR 51, you'll notice there is mention of scanning and formatting support, similar to C's <code>printf</code>. This feature didn't make the 1.4 beta release and will be saved for a later version. <a name="Resources"></a>
<h5>Resources</h5>
<ul>
<li><a href="http://www.jcp.org/jsr/detail/51.jsp">JSR 51 New I/O APIs for the Java Platform</a> 
<li><a href="http://java.sun.com/j2se/1.4.2/docs/guide/nio/index.html">New I/O API Summary</a> 
<li><a href="http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html">JNI Enhancements</a> 
<li><a href="http://java.sun.com/developer/technicalArticles/releases/1.4regex/">Regular Expressions and the Java Programming Language</a> 
<li><a href="http://www.iana.org/assignments/character-sets">Character Sets</a> 
<li><a href="http://www.javaworld.com/javaworld/jw-09-2001/jw-0907-merlin.html">Master Merlin's new I/O classes</a> (JavaWorld) 
<li><a href="http://www.owlmountain.com/tutorials/NonBlockingIo.htm">Non-Blocking Socket I/O in JDK 1.4</a></li></ul><a name="author"></a>
<h5>About the Author</h5>
<p>John Zukowski conducts strategic Java consulting with <a href="http://www.jzventures.com">JZ Ventures, Inc.</a> His latest books are <a href="http://www.amazon.com/exec/obidos/ASIN/1893115925/johnzukowshomefo/"><i>Java Collections</i></a> and <a href="http://www.amazon.com/exec/obidos/ASIN/189311578X/johnzukowshomefo/"><i>Definitive Guide to Swing for Java 2</i></a> (2nd ed) from Apress. Look for <a href="http://www.amazon.com/exec/obidos/ASIN/1893115984/johnzukowshomefo/"><i>Learn Java with JBuilder 6</i></a> in 2002. Contact John at <a href="mailto:jaz@zukowski.net?Subject=New%20I/O%20Article">jaz@zukowski.net</a>. </p><img src ="http://www.blogjava.net/cherishchen/aggbug/326000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-07-13 19:07 <a href="http://www.blogjava.net/cherishchen/archive/2010/07/13/326000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>How Java allocate memory</title><link>http://www.blogjava.net/cherishchen/articles/324557.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Sat, 26 Jun 2010 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/articles/324557.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/324557.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/articles/324557.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/324557.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/324557.html</trackback:ping><description><![CDATA[<p>There are two kinds of memory used in Java. These are called stack
memory and
heap memory.<strong> Stack memory stores primitive types and the addresses of
objects.</strong>
The object values are stored in heap memory. An object reference on the
stack is
only an address that refers to the place in heap memory where that
object is
kept. <br />
</p>
<p><br />
</p>
<img src ="http://www.blogjava.net/cherishchen/aggbug/324557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-06-26 16:00 <a href="http://www.blogjava.net/cherishchen/articles/324557.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>the rule of thumb</title><link>http://www.blogjava.net/cherishchen/archive/2010/06/12/323460.html</link><dc:creator>凭栏观海</dc:creator><author>凭栏观海</author><pubDate>Sat, 12 Jun 2010 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/cherishchen/archive/2010/06/12/323460.html</guid><wfw:comment>http://www.blogjava.net/cherishchen/comments/323460.html</wfw:comment><comments>http://www.blogjava.net/cherishchen/archive/2010/06/12/323460.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/cherishchen/comments/commentRss/323460.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/cherishchen/services/trackbacks/323460.html</trackback:ping><description><![CDATA[<p>the rule of thumb</p> <p>拇指法则 <p>【摘要】 亦即凭借经验来解决问题, 也称为经验法则或拇指法则( the rule of thumb) 。</p><img src ="http://www.blogjava.net/cherishchen/aggbug/323460.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/cherishchen/" target="_blank">凭栏观海</a> 2010-06-12 17:36 <a href="http://www.blogjava.net/cherishchen/archive/2010/06/12/323460.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>