﻿<?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>C++博客-雪黛依梦-随笔分类-JAVA--J2SE</title><link>http://www.cppblog.com/wing/category/17362.html</link><description>幸福的飞翔——简单世界</description><language>zh-cn</language><lastBuildDate>Tue, 26 Jul 2011 01:42:58 GMT</lastBuildDate><pubDate>Tue, 26 Jul 2011 01:42:58 GMT</pubDate><ttl>60</ttl><item><title>生产者消费者问题(wait、notify、 notifyAll用法示例)</title><link>http://www.cppblog.com/wing/archive/2011/07/25/151819.html</link><dc:creator>雪黛依梦</dc:creator><author>雪黛依梦</author><pubDate>Mon, 25 Jul 2011 12:10:00 GMT</pubDate><guid>http://www.cppblog.com/wing/archive/2011/07/25/151819.html</guid><wfw:comment>http://www.cppblog.com/wing/comments/151819.html</wfw:comment><comments>http://www.cppblog.com/wing/archive/2011/07/25/151819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wing/comments/commentRss/151819.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wing/services/trackbacks/151819.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 例子：有一家汉堡店举办吃汉堡比赛，决赛时有3个顾客来吃，3个厨师来做，一个服务员负责协调汉堡的数量。为了避免浪费，制作好的汉堡被放进一个能装有10个汉堡的长条状容器中，按照先进先出的原则取汉堡。如果容器被装满，则厨师停止做汉堡，如果顾客发现容器内的汉堡吃完了，就可以拍响容器上的闹铃，提醒厨师再做几个汉堡出来。此时服务员过来安抚顾客，让他等待。而一旦厨师的汉堡做出来，就会让服务员通知顾客，汉堡做好了...&nbsp;&nbsp;<a href='http://www.cppblog.com/wing/archive/2011/07/25/151819.html'>阅读全文</a><img src ="http://www.cppblog.com/wing/aggbug/151819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wing/" target="_blank">雪黛依梦</a> 2011-07-25 20:10 <a href="http://www.cppblog.com/wing/archive/2011/07/25/151819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Java线程：线程的同步与锁</title><link>http://www.cppblog.com/wing/archive/2011/07/23/151713.html</link><dc:creator>雪黛依梦</dc:creator><author>雪黛依梦</author><pubDate>Sat, 23 Jul 2011 12:50:00 GMT</pubDate><guid>http://www.cppblog.com/wing/archive/2011/07/23/151713.html</guid><wfw:comment>http://www.cppblog.com/wing/comments/151713.html</wfw:comment><comments>http://www.cppblog.com/wing/archive/2011/07/23/151713.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wing/comments/commentRss/151713.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wing/services/trackbacks/151713.html</trackback:ping><description><![CDATA[<div><strong>一、同步问题提出</strong></div>
<div></div>
<div>线程的同步是为了防止多个线程访问一个数据对象时，对数据造成的破坏。</div>
<div>例如：两个线程ThreadA、ThreadB都操作同一个对象Foo对象，并修改Foo对象上的数据。</div>
<div></div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px">package thread;<br /><br />public class Foo {<br />private static int x = 100;<br /><br />public int getX() {<br />return x;<br />}<br /><br />public int fix(int y) {<br />x = x - y;<br />try {<br />Thread.currentThread().sleep(1);<br />} catch (InterruptedException e) {<br />e.printStackTrace();<br />}<br />System.out.println(Thread.currentThread().getName()<br />＋ " : 当前foo对象的x值=" ＋ getX());<br />return x;<br />}<br />}<br /><br />package thread;<br /><br />public class SynchronizedDemo implements Runnable {<br />private Foo foo = new Foo();<br /><br />public void run() {<br />for (int i = 0; i &lt; 100; i＋＋) {<br />this.fix(30);<br />}<br />}<br /><br />public int fix(int y) {<br />return foo.fix(y);<br />}<br /><br />public static void main(String[] args) {<br />SynchronizedDemo a = new SynchronizedDemo();<br />Thread tha = new Thread(a, "A");<br />Thread thb = new Thread(a, "B");<br />Thread thc = new Thread(a, "C");<br />Thread thd = new Thread(a, "D");<br />Thread the = new Thread(a, "E");<br />Thread thf = new Thread(a, "F");<br />Thread thg = new Thread(a, "G");<br />Thread thh = new Thread(a, "H");<br />Thread thi = new Thread(a, "I");<br />Thread thj = new Thread(a, "J");<br />Thread thk = new Thread(a, "K");<br />tha.start();<br />thb.start();<br />thc.start();<br />thd.start();<br />the.start();<br />thf.start();<br />thg.start();<br />thh.start();<br />thi.start();<br />thj.start();<br />thk.start();<br />}<br />}<br /></div></div></div>
<div></div>
<div>
<div>&nbsp;</div></div>
<div></div>
<div>运行
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><br /></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></font></div>结果：</div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"></div></div></div>
<div></div>
<div>从结果发现，这样的输出值明显是不合理的。原因是两个线程不加控制的访问Foo对象并修改其数据所致。</div>
<div></div>
<div>如果要保持结果的合理性，只需要达到一个目的，就是将对Foo的访问加以限制，每次只能有一个线程在访问。这样就能保证Foo对象中数据的合理性了。</div>
<div></div>
<div>在具体的Java代码中需要完成一下两个操作：</div>
<div>把竞争访问的资源类Foo变量x标识为private；</div>
<div>同步哪些修改变量的代码，使用synchronized关键字同步方法或代码。</div>
<div></div>
<div><strong>二、同步和锁定</strong></div>
<div></div>
<div>1、锁的原理</div>
<div></div>
<div>Java中每个对象都有一个内置锁</div>
<div></div>
<div>当程序运行到非静态的synchronized同步方法上时，自动获得与正在执行代码类的当前实例（this实例）有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。</div>
<div></div>
<div>当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。</div>
<div></div>
<div>一个对象只有一个锁。所以，如果一个线程获得该锁，就没有其他线程可以获得锁，直到第一个线程释放（或返回）锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块，直到该锁被释放。</div>
<div></div>
<div>释放锁是指持锁线程退出了synchronized同步方法或代码块。</div>
<div></div>
<div>关于锁和同步，有一下几个要点：</div>
<div>1）、只能同步方法，而不能同步变量和类；</div>
<div>2）、每个对象只有一个锁；当提到同步时，应该清楚在什么上同步？也就是说，在哪个对象上同步？</div>
<div>3）、不必同步类中所有的方法，类可以同时拥有同步和非同步方法。</div>
<div>4）、如果两个线程要执行一个类中的synchronized方法，并且两个线程使用相同的实例来调用方法，那么一次只能有一个线程能够执行方法，另一个需要等待，直到锁被释放。也就是说：如果一个线程在对象上获得一个锁，就没有任何其他线程可以进入（该对象的）类中的任何一个同步方法。</div>
<div>5）、如果线程拥有同步和非同步方法，则非同步方法可以被多个线程自由访问而不受锁的限制。</div>6）、线程睡眠时，它所持的任何锁都不会释放。 
<div>7）、线程可以获得多个锁。比如，在一个对象的同步方法里面调用另外一个对象的同步方法，则获取了两个对象的同步锁。</div>
<div>8）、同步损害并发性，应该尽可能缩小同步范围。同步不但可以同步整个方法，还可以同步方法中一部分代码块。</div>
<div>9）、在使用同步代码块时候，应该指定在哪个对象上同步，也就是说要获取哪个对象的锁。例如：</div>
<div>public int fix(int y) {<br />synchronized (this) {<br />x = x - y;<br />}<br />return x;<br />}</div>
<div></div>
<div>当然，同步方法也可以改写为非同步方法，但功能完全一样的，例如：</div>
<div>public synchronized int getX() {<br />return x++;<br />}</div>
<div>与</div>
<div>public int getX() {<br />synchronized (this) {<br />return x;<br />}<br />}</div>
<div>效果是完全一样的。</div>
<div></div>
<div><strong>三、静态方法同步</strong></div>
<div></div>
<div>要同步静态方法，需要一个用于整个类对象的锁，这个对象是就是这个类（XXX.class)。</div>
<div>例如：</div>
<div>public static synchronized int setName(String name){</div>
<div>Xxx.name = name;</div>
<div>}</div>
<div>等价于<br />public static int setName(String name){<br />synchronized(Xxx.class){<br />Xxx.name = name;<br />}<br />}</div>
<div><br /></div>
<div><strong>四、如果线程不能不能获得锁会怎么样</strong></div>
<div></div>
<div>如果线程试图进入同步方法，而其锁已经被占用，则线程在该对象上被阻塞。实质上，线程进入该对象的的一种池中，必须在哪里等待，直到其锁被释放，该线程再次变为可运行或运行为止。</div>
<div></div>
<div>当考虑阻塞时，一定要注意哪个对象正被用于锁定：</div>
<div>1、调用同一个对象中非静态同步方法的线程将彼此阻塞。如果是不同对象，则每个线程有自己的对象的锁，线程间彼此互不干预。</div>
<div></div>
<div>2、调用同一个类中的静态同步方法的线程将彼此阻塞，它们都是锁定在相同的Class对象上。</div>
<div></div>
<div>3、静态同步方法和非静态同步方法将永远不会彼此阻塞，因为静态方法锁定在Class对象上，非静态方法锁定在该类的对象上。</div>
<div></div>
<div>4、对于同步代码块，要看清楚什么对象已经用于锁定（synchronized后面括号的内容）。在同一个对象上进行同步的线程将彼此阻塞，在不同对象上锁定的线程将永远不会彼此阻塞。</div>
<div></div>
<div><strong>五、何时需要同步</strong></div>
<div></div>
<div>在多个线程同时访问互斥（可交换）数据时，应该同步以保护数据，确保两个线程不会同时修改更改它。</div>
<div></div>
<div>对于非静态字段中可更改的数据，通常使用非静态方法访问。</div>
<div>
<div>对于静态字段中可更改的数据，通常使用静态方法访问。</div>
<div></div>
<div>如果需要在非静态方法中使用静态字段，或者在静态字段中调用非静态方法，问题将变得非常复杂。已经超出SJCP考试范围了。</div>
<div></div>
<div><strong>六、线程安全类</strong></div>
<div></div>
<div>当一个类已经很好的同步以保护它的数据时，这个类就称为&#8220;线程安全的&#8221;。</div>
<div></div>
<div>即使是线程安全类，也应该特别小心，因为操作的线程是间仍然不一定安全。</div>
<div></div>
<div>举个形象的例子，比如一个集合是线程安全的，有两个线程在操作同一个集合对象，当第一个线程查询集合非空后，删除集合中所有元素的时候。第二个线程也来执行与第一个线程相同的操作，也许在第一个线程查询后，第二个线程也查询出集合非空，但是当第一个执行清除后，第二个再执行删除显然是不对的，因为此时集合已经为空了。</div>
<div>看个代码：</div>
<div></div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font color="#0000ff">public</font> <font color="#0000ff">class</font></font> NameList { <br /><font color="#0000ff">private</font></font> List nameList = Collections.synchronizedList(<font color="#0000ff">new</font></font> LinkedList()); <br /><br /><font color="#0000ff">public</font></font> <font color="#0000ff">void</font></font> add(String name) { <br />nameList.add(name); <br />} <br /><br /><font color="#0000ff">public</font></font> String removeFirst() { <br /><font color="#0000ff">if</font></font> (nameList.size() &gt; 0) { <br /><font color="#0000ff">return</font></font> (String) nameList.remove(0); <br />} <font color="#0000ff">else</font></font> { <br /><font color="#0000ff">return</font></font> <font color="#0000ff">null</font></font>; <br />} <br />} <br />}</div></div></div>
<div></div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font color="#0000ff">public</font> <font color="#0000ff">class</font></font> Test { <br /><font color="#0000ff">public</font></font> <font color="#0000ff">static</font></font> <font color="#0000ff">void</font></font> main(String[] args) { <br /><font color="#0000ff">final</font></font> NameList nl = <font color="#0000ff">new</font></font> NameList(); <br />nl.add(<font color="#800000">"aaa"</font></font>); <br /><font color="#0000ff">class</font></font> NameDropper <font color="#0000ff">extends</font></font> Thread{ <br /><font color="#0000ff">public</font></font> <font color="#0000ff">void</font></font> run(){ <br />String name = nl.removeFirst(); <br />System.out.println(name); <br />} <br />} <br /><br />Thread t1 = <font color="#0000ff">new</font></font> NameDropper(); <br />Thread t2 = <font color="#0000ff">new</font></font> NameDropper(); <br />t1.start(); <br />t2.start(); <br />} <br />}</div></div></div>
<div></div>
<div>虽然集合对象</div>
<div>private List nameList = Collections.synchronizedList(new LinkedList());<br />是同步的，但是程序还不是线程安全的。</div>
<div>出现这种事件的原因是，上例中一个线程操作列表过程中无法阻止另外一个线程对列表的其他操作。</div>
<div></div>
<div>解决上面问题的办法是，在操作集合对象的NameList上面做一个同步。改写后的代码如下：</div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font color="#0000ff">public</font> <font color="#0000ff">class</font></font> NameList { <br /><font color="#0000ff">private</font></font> List nameList = Collections.synchronizedList(<font color="#0000ff">new</font></font> LinkedList()); <br /><br /><font color="#0000ff">public</font></font> <font color="#0000ff">synchronized</font></font> <font color="#0000ff">void</font></font> add(String name) { <br />nameList.add(name); <br />} <br /><br /><font color="#0000ff">public</font></font> <font color="#0000ff">synchronized</font></font> String removeFirst() { <br /><font color="#0000ff">if</font></font> (nameList.size() &gt; 0) { <br /><font color="#0000ff">return</font></font> (String) nameList.remove(0); <br />} <font color="#0000ff">else</font></font> { <br /><font color="#0000ff">return</font></font> <font color="#0000ff">null</font></font>; <br />} <br />} <br />}</div></div></div>
<div></div></div>
<div>这样，当一个线程访问其中一个同步方法时，其他线程只有等待。</div>
<div></div>
<div><strong>七、线程死锁</strong></div>
<div></div>
<div>死锁对Java程序来说，是很复杂的，也很难发现问题。当两个线程被阻塞，每个线程在等待另一个线程时就发生死锁。</div>
<div></div>
<div>还是看一个比较直观的死锁例子：</div>
<div></div>
<div>
<div>
<div style="border-bottom: rgb(204,204,204) 1px solid; border-left: rgb(204,204,204) 1px solid; padding-bottom: 4px; line-height: 16px; background-color: rgb(238,238,238); padding-left: 4px; width: 98%; padding-right: 4px; font-family: verdana, 宋体; color: rgb(0,0,0); font-size: 10pt; word-break: break-all; border-top: rgb(204,204,204) 1px solid; border-right: rgb(204,204,204) 1px solid; padding-top: 4px"><font style="background-color: #eeeeee"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font size="+0"><font color="#0000ff">public</font> <font color="#0000ff">class</font></font> DeadlockRisk { <br /><font color="#0000ff">private</font></font> <font color="#0000ff">static</font></font> <font color="#0000ff">class</font></font> Resource { <br /><font color="#0000ff">public</font></font> <font color="#0000ff">int</font></font> value; <br />} <br /><br /><font color="#0000ff">private</font></font> Resource resourceA = <font color="#0000ff">new</font></font> Resource(); <br /><font color="#0000ff">private</font></font> Resource resourceB = <font color="#0000ff">new</font></font> Resource(); <br /><br /><font color="#0000ff">public</font></font> <font color="#0000ff">int</font></font> read() { <br /><font color="#0000ff">synchronized</font></font> (resourceA) { <br /><font color="#0000ff">synchronized</font></font> (resourceB) { <br /><font color="#0000ff">return</font></font> resourceB.value + resourceA.value; <br />} <br />} <br />} <br /><br /><font color="#0000ff">public</font></font> <font color="#0000ff">void</font></font> write(<font color="#0000ff">int</font></font> a, <font color="#0000ff">int</font></font> b) { <br /><font color="#0000ff">synchronized</font></font> (resourceB) { <br /><font color="#0000ff">synchronized</font></font> (resourceA) { <br />resourceA.value = a; <br />resourceB.value = b; <br />} <br />} <br />} <br />}</div></div></div>
<div></div>
<div>假设read()方法由一个线程启动，write()方法由另外一个线程启动。读线程将拥有resourceA锁，写线程将拥有resourceB锁，两者都坚持等待的话就出现死锁。</div>
<div></div>
<div>实际上，上面这个例子发生死锁的概率很小。因为在代码内的某个点，CPU必须从读线程切换到写线程，所以，死锁基本上不能发生。</div>
<div></div>
<div>但是，无论代码中发生死锁的概率有多小，一旦发生死锁，程序就死掉。有一些设计方法能帮助避免死锁，包括始终按照预定义的顺序获取锁这一策略。已经超出SCJP的考试范围。</div>
<div></div>
<div><strong>八、线程同步小结</strong></div>
<div></div>
<div>1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。</div>
<div>2、线程同步方法是通过锁来实现，每个对象都有切仅有一个锁，这个锁与一个特定的对象关联，线程一旦获取了对象锁，其他访问该对象的线程就无法再访问该对象的其他同步方法。</div>
<div>3、对于静态同步方法，锁是针对这个类的，锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁，当在一个同步方法中访问另外对象上的同步方法时，会获取这两个对象锁。</div>
<div>4、对于同步，要时刻清醒在哪个对象上同步，这是关键。</div>
<div>5、编写线程安全的类，需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断，对&#8220;原子&#8221;操作做出分析，并保证原子操作期间别的线程无法访问竞争资源。</div>
<div>6、当多个线程等待一个对象锁时，没有获取到锁的线程将发生阻塞。</div>
<div>7、死锁是线程间相互等待锁锁造成的，在实际中发生的概率非常的小。真让你写个死锁程序，不一定好使，呵呵。但是，一旦程序发生死锁，程序将死掉。</div>
<div></div>
<p>&nbsp;</p>
<div class="artComm box">
<div id="artcomment" class="modCon">
<div style="word-wrap: break-word; table-layout: fixed" id="itcommentid1" class="itcomment">
<div align="right">2010-02-22 11:39:12</div>
<div class="commentcontent">博主的第一个线程同步的例子应该这样举才合适吧<br />package thread;<br /><br />public class Foo {<br />private static int x = 100;<br /><br />public int getX() {<br />return x;<br />}<br /><br />public int fix(int y) {<br />x = x - y;<br />try {<br />Thread.currentThread().sleep(1);<br />} catch (InterruptedException e) {<br />e.printStackTrace();<br />}<br />System.out.println(Thread.currentThread().getName()<br />＋ " : 当前foo对象的x值=" ＋ getX());<br />return x;<br />}<br />}<br /><br />package thread;<br /><br />public class SynchronizedDemo implements Runnable {<br />private Foo foo = new Foo();<br /><br />public void run() {<br />for (int i = 0; i &lt; 100; i＋＋) {<br />this.fix(30);<br />}<br />}<br /><br />public int fix(int y) {<br />return foo.fix(y);<br />}<br /><br />public static void main(String[] args) {<br />SynchronizedDemo a = new SynchronizedDemo();<br />Thread tha = new Thread(a, "A");<br />Thread thb = new Thread(a, "B");<br />Thread thc = new Thread(a, "C");<br />Thread thd = new Thread(a, "D");<br />Thread the = new Thread(a, "E");<br />Thread thf = new Thread(a, "F");<br />Thread thg = new Thread(a, "G");<br />Thread thh = new Thread(a, "H");<br />Thread thi = new Thread(a, "I");<br />Thread thj = new Thread(a, "J");<br />Thread thk = new Thread(a, "K");<br />tha.start();<br />thb.start();<br />thc.start();<br />thd.start();<br />the.start();<br />thf.start();<br />thg.start();<br />thh.start();<br />thi.start();<br />thj.start();<br />thk.start();<br />}<br />}<br /></div></div></div></div><img src ="http://www.cppblog.com/wing/aggbug/151713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wing/" target="_blank">雪黛依梦</a> 2011-07-23 20:50 <a href="http://www.cppblog.com/wing/archive/2011/07/23/151713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>进程与Java线程的区别</title><link>http://www.cppblog.com/wing/archive/2011/07/22/151631.html</link><dc:creator>雪黛依梦</dc:creator><author>雪黛依梦</author><pubDate>Fri, 22 Jul 2011 06:04:00 GMT</pubDate><guid>http://www.cppblog.com/wing/archive/2011/07/22/151631.html</guid><wfw:comment>http://www.cppblog.com/wing/comments/151631.html</wfw:comment><comments>http://www.cppblog.com/wing/archive/2011/07/22/151631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wing/comments/commentRss/151631.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wing/services/trackbacks/151631.html</trackback:ping><description><![CDATA[<center><font color="#000099"><strong>进程与Java线程的区别</strong></font></center>
<p><br /><br />应用程序在执行过程中存在一个内存空间的初始入口点地址、一个程序执行过程中的代码执行序列以及用于标识进程结束的内存出口点地址，在进程执行过程中的每一时间点均有唯一的处理器指令与内存单元地址相对应。 <br /><br />Java语言中定义的线程（Thread）同样包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列。但是进程与线程的重要区别在于线程不能够单独执行，它必须运行在处于活动状态的应用程序进程中，因此可以定义<span style="color: red"><strong>线程是程序内部的具有并发性的顺序代码流</strong></span>。 <br /><br />Unix操作系统和Microsoft Windows操作系统支持多用户、多进程的并发执行，而Java语言支持应用程序进程内部的多个执行线程的并发执行。<span style="color: red">多线程的意义在于一个应用程序的多个逻辑单元可以并发地执行。</span>但是多线程并不意味着多个用户进程在执行，操作系统也不把每个线程作为独立的进程来分配独立的系统资源。进程可以创建其子进程，子进程与父进程拥有不同的可执行代码和数据内存空间。而在用于代表应用程序的进程中多个线程共享数据内存空间，但保持每个线程拥有独立的执行堆栈和程序执行上下文（Context）。 <br /><br />基于上述区别，线程也可以称为轻型进程 (Light Weight Process，LWP)。不同线程间允许任务协作和数据交换，使得在计算机系统资源消耗等方面非常廉价。 <br /><br />线程需要操作系统的支持，不是所有类型的计算机都支持多线程应用程序。<span style="color: red">Java程序设计语言将线程支持与语言运行环境结合在一起，提供了多任务并发执行的能力。</span>这就好比一个人在处理家务的过程中，将衣服放到洗衣机中自动洗涤后将大米放在电饭锅里，然后开始做菜。等菜做好了，饭熟了同时衣服也洗好了。 <br /><br />需要注意的是：在应用程序中使用多线程不会增加 CPU 的数据处理能力。只有在多CPU 的计算机或者在网络计算体系结构下，将Java程序划分为多个并发执行线程后，同时启动多个线程运行，使不同的线程运行在基于不同处理器的Java虚拟机中，才能提高应用程序的执行效率。 </p><img src ="http://www.cppblog.com/wing/aggbug/151631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wing/" target="_blank">雪黛依梦</a> 2011-07-22 14:04 <a href="http://www.cppblog.com/wing/archive/2011/07/22/151631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.io中serializable讲解</title><link>http://www.cppblog.com/wing/archive/2011/07/22/151614.html</link><dc:creator>雪黛依梦</dc:creator><author>雪黛依梦</author><pubDate>Fri, 22 Jul 2011 03:08:00 GMT</pubDate><guid>http://www.cppblog.com/wing/archive/2011/07/22/151614.html</guid><wfw:comment>http://www.cppblog.com/wing/comments/151614.html</wfw:comment><comments>http://www.cppblog.com/wing/archive/2011/07/22/151614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wing/comments/commentRss/151614.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wing/services/trackbacks/151614.html</trackback:ping><description><![CDATA[<strong>1、序列化是干什么的？<br /></strong>简单说就是为了保存在内存中的各种对象的状态（也就是实例变量，不是方法），并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states，但是Java给你提供一种应该比你自己好的保存对象状态的机制，那就是序列化。<br /><br /><strong>2、什么情况下需要序列化 </strong><br />a）当你想把的内存中的对象状态保存到一个文件中或者数据库中时候；<br />b）当你想用套接字在网络上传送对象的时候；<br />c）当你想通过RMI传输对象的时候；<br /><br /><strong>3、当对一个对象实现序列化时，究竟发生了什么？</strong><br />在没有序列化前，每个保存在堆（Heap）中的对象都有相应的状态（state），即实例变量（instance ariable）比如：<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span>Foo myFoo = </span><span class="keyword"><font color="#7f0055">new</font></span><span> Foo(); </span></li><li><span>myFoo .setWidth(<span class="number">37</span><span>); </span></span></li><li class="alt"><span>myFoo.setHeight(<span class="number">70</span><span>); </span></span></li></ol></div><br />当 通过下面的代码序列化之后，MyFoo对象中的width和Height实例变量的值（37，70）都被保存到foo.ser文件中，这样以后又可以把它 从文件中读出来，重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值，JVM还要保存一些小量信息，比如类的类型等以便恢复原来的对 象。<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span>FileOutputStream fs = </span><span class="keyword"><font color="#7f0055">new</font></span><span> FileOutputStream(</span><span class="string">"foo.ser"</span><span>); </span></li><li><span>ObjectOutputStream os = <span class="keyword"><font color="#7f0055">new</font></span><span> ObjectOutputStream(fs); </span></span></li><li class="alt"><span>os.writeObject(myFoo); </span></li></ol></div><br /><strong>4、实现序列化（保存到一个文件）的步骤<br /></strong>a）Make a FileOutputStream <strong><span><strong>
<div class="code_title"><strong>java 代码</strong></div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span><strong>FileOutputStream fs = </strong></span><span class="keyword"><strong><font color="#7f0055">new</font></strong></span><span><strong> FileOutputStream(</strong></span><span class="string"><strong>"foo.ser"</strong></span><span><strong>); </strong></span></li></ol></div><span></span></strong></span></strong>b）Make a ObjectOutputStream <br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span>ObjectOutputStream os = </span><span class="keyword"><font color="#7f0055">new</font></span><span> ObjectOutputStream(fs); </span></li></ol></div>c）write the object<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span>os.writeObject(myObject1); </span></li><li><span>os.writeObject(myObject2); </span></li><li class="alt"><span>os.writeObject(myObject3); </span></li></ol></div>d) close the ObjectOutputStream<br />
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<ol class="dp-j"><li class="alt"><span>os.close(); </span></li></ol></div><strong>相关注意事项<br /></strong>a）序列化时，只对对象的状态进行保存，而不管对象的方法；<br />b）当一个父类实现序列化，子类自动实现序列化，不需要显式实现Serializable接口；<br />c）当一个对象的实例变量引用其他对象，序列化该对象时也把引用对象进行序列化；<br />d）并非所有的对象都可以序列化，,至于为什么不可以，有很多原因了,比如：<br />1.安全方面的原因，比如一个对象拥有private，public等field，对于一个要传输的对象，比如写到文件，或者进行rmi传输 等等，在序列化进行传输的过程中，这个对象的private等域是不受保护的。<br />2. 资源分配方面的原因，比如socket，thread类，如果可以序列化，进行传输或者保存，也无法对他们进行重新的资源分 配，而且，也是没有必要这样实现。 <br /><img src ="http://www.cppblog.com/wing/aggbug/151614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wing/" target="_blank">雪黛依梦</a> 2011-07-22 11:08 <a href="http://www.cppblog.com/wing/archive/2011/07/22/151614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java缓冲流中mark（）和reset（）函数用法解析</title><link>http://www.cppblog.com/wing/archive/2011/07/21/151545.html</link><dc:creator>雪黛依梦</dc:creator><author>雪黛依梦</author><pubDate>Thu, 21 Jul 2011 06:46:00 GMT</pubDate><guid>http://www.cppblog.com/wing/archive/2011/07/21/151545.html</guid><wfw:comment>http://www.cppblog.com/wing/comments/151545.html</wfw:comment><comments>http://www.cppblog.com/wing/archive/2011/07/21/151545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/wing/comments/commentRss/151545.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/wing/services/trackbacks/151545.html</trackback:ping><description><![CDATA[<p>根据JAVA官方文档的描述，mark(int readlimit)方法表示，标记当前位置，并保证在mark以后最多可以读取readlimit字节<span class="t_tag" href="tag.php?name=%CA%FD%BE%DD">数据</span>，mark标记仍有效。如果在mark后读取超过readlimit字节数据，mark标记就会失效，调用reset()方法会有异常。 <br />但实际的运行情况却和JAVA文档中的描述并不完全相符。 有时候在BufferedInputStream类中调用mark(int readlimit)方法后，即使读取超过readlimit字节的数据，mark标记仍有效，仍然能正确调用reset方法重置。 </p>
<p>事实上，mark在JAVA中的实现是和缓冲区相关的。只要缓冲区够大，mark后读取的数据没有超出缓冲区的大小，mark标记就不会失效。如果不够大，mark后又读取了大量的数据，导致缓冲区更新，原来标记的位置自然找不到了。</p>
<p>因此，mark后读取多少字节才失效，并不完全由readlimit参数确定，也和BufferedInputStream类的缓冲区大小有关。 如果BufferedInputStream类的缓冲区大小大于readlimit，在mark以后只有读取超过缓冲区大小的数据，mark标记才会失效。看下面的例子。 </p>
<div class="cnblogs_Highlighter">
<div id="highlighter_650670" class="syntaxhighlighter nogutter  java">
<div class="bar                                                                                                                                                                                                                                                                                                                                                                                        show">
<div class="toolbar"><a style="width: 16px; height: 16px" class="item viewSource" title="view source" href="http://www.cnblogs.com/zhang-qiang/articles/2050885.html#viewSource">view source</a><a style="width: 16px; height: 16px" class="item printSource" title="print" href="http://www.cnblogs.com/zhang-qiang/articles/2050885.html#printSource">print</a><a style="width: 16px; height: 16px" class="item about" title="?" href="http://www.cnblogs.com/zhang-qiang/articles/2050885.html#about">?</a></div></div>
<div class="lines">
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="java plain">&lt;span style=</code><code class="java string"><font color="#0000ff">"color: rgb(255, 0, 0);"</font></code><code class="java plain">&gt;ava代码 </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java keyword"><strong><font color="#006699">package</font></strong></code> <code class="java plain">packet1; </code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java keyword"><strong><font color="#006699">import</font></strong></code> <code class="java plain">java.io.BufferedInputStream; </code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="java keyword"><strong><font color="#006699">import</font></strong></code> <code class="java plain">java.io.ByteArrayInputStream; </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java keyword"><strong><font color="#006699">import</font></strong></code> <code class="java plain">java.io.IOException; </code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java preprocessor"><font color="#808080">/** </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="java preprocessor"><font color="#808080">* @author WuDian </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java preprocessor"><font color="#808080">* </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="java preprocessor"><font color="#808080">*/</font></code> </td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java keyword"><strong><font color="#006699">public</font></strong></code> <code class="java keyword"><strong><font color="#006699">class</font></strong></code> <code class="java plain">MarkExample { </code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java keyword"><strong><font color="#006699">public</font></strong></code> <code class="java keyword"><strong><font color="#006699">static</font></strong></code> <code class="java keyword"><strong><font color="#006699">void</font></strong></code> <code class="java plain">main(String[] args) { </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java keyword"><strong><font color="#006699">try</font></strong></code> <code class="java plain">{ </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 初始化一个字节数组，内有5个字节的数据 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java keyword"><strong><font color="#006699">byte</font></strong></code><code class="java plain">[] bytes={</code><code class="java value"><font color="#009900">1</font></code><code class="java plain">,</code><code class="java value"><font color="#009900">2</font></code><code class="java plain">,</code><code class="java value"><font color="#009900">3</font></code><code class="java plain">,</code><code class="java value"><font color="#009900">4</font></code><code class="java plain">,</code><code class="java value"><font color="#009900">5</font></code><code class="java plain">}; </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 用一个ByteArrayInputStream来读取这个字节数组 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java plain">ByteArrayInputStream in=</code><code class="java keyword"><strong><font color="#006699">new</font></strong></code> <code class="java plain">ByteArrayInputStream(bytes); </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 将ByteArrayInputStream包含在一个BufferedInputStream，并初始化缓冲区大小为2。 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java plain">BufferedInputStream bis=</code><code class="java keyword"><strong><font color="#006699">new</font></strong></code> <code class="java plain">BufferedInputStream(in,</code><code class="java value"><font color="#009900">2</font></code><code class="java plain">); </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 读取字节1 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java plain">System.out.print(bis.read()+</code><code class="java string"><font color="#0000ff">","</font></code><code class="java plain">); </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 在字节2处做标记，同时设置readlimit参数为1 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 根据JAVA文档mark以后最多只能读取1个字节，否则mark标记失效，但实际运行结果不是这样 </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java plain">System.out.println(</code><code class="java string"><font color="#0000ff">"mark"</font></code><code class="java plain">); </code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java plain">bis.mark(</code><code class="java value"><font color="#009900">1</font></code><code class="java plain">); </code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">/* </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">* 连续读取两个字节，超过了readlimit的大小，mark标记仍有效 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">*/ </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 连续读取两个字节 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.print(bis.read()+","); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.print(bis.read()+","); </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 调用reset方法，未发生异常，说明mark标记仍有效。 </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 因为，虽然readlimit参数为1，但是这个BufferedInputStream类的缓冲区大小为2， </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 所以允许读取2字节 </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.println("reset"); </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">bis.reset(); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"><font color="#008200"></font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">/* </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">* 连续读取3个字节，超过了缓冲区大小，mark标记失效。 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">* 在这个例子中BufferedInputStream类的缓冲区大小大于readlimit, </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">* mark标记由缓冲区大小决定 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">*/ </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// reset重置后连续读取3个字节，超过了BufferedInputStream类的缓冲区大小 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.print(bis.read()+","); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.print(bis.read()+","); </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.print(bis.read()+","); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// 再次调用reset重置，抛出异常，说明mark后读取3个字节，mark标记失效 </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">System.out.println("reset again"); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">bis.reset(); </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">} catch (IOException e) { </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">// TODO Auto-generated catch block </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">e.printStackTrace(); </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">} </font></code></td></tr></tbody></table></div>
<div class="line alt1">
<table>
<tbody>
<tr>
<td class="content"><code class="spaces"></code><code class="java comments"><font color="#008200">} </font></code></td></tr></tbody></table></div>
<div class="line alt2">
<table>
<tbody>
<tr>
<td class="content"><code class="java comments"><font color="#008200">} </font></code></td></tr></tbody></table></div></div></div></div><img src ="http://www.cppblog.com/wing/aggbug/151545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/wing/" target="_blank">雪黛依梦</a> 2011-07-21 14:46 <a href="http://www.cppblog.com/wing/archive/2011/07/21/151545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>