﻿<?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-上善若水-随笔分类-CodeTools</title><link>http://blogjava.net/DLevin/category/49040.html</link><description>In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation.
To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra</description><language>zh-cn</language><lastBuildDate>Thu, 13 Aug 2015 10:48:08 GMT</lastBuildDate><pubDate>Thu, 13 Aug 2015 10:48:08 GMT</pubDate><ttl>60</ttl><item><title>实现自己的Lock对象</title><link>http://www.blogjava.net/DLevin/archive/2015/08/11/426723.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 10 Aug 2015 22:08:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2015/08/11/426723.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/426723.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2015/08/11/426723.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/426723.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/426723.html</trackback:ping><description><![CDATA[<p>一直想好好学习concurrent包中的各个类的实现，然而经常看了一点就因为其他事情干扰而放下了。发现这样太不利于自己的成长了，因而最近打算潜心一件一件的完成自己想学习的东西。<br /><br />对concurrent包的学习打算先从Lock的实现开始，因而自然而然的就端起了AbstractQueuedSynchronizer，然而要读懂这个类的源码并不是那么容易，因而我就开始问自己一个问题：如果自己要去实现这个一个Lock对象，应该如何实现呢？<br /><br />要实现Lock对象，首先理解什么是锁？我自己从编程角度简单的理解，所谓锁对象（互斥锁）就是它能保证一次只有一个线程能进入它保护的临界区，如果有一个线程已经拿到锁对象，那么其他对象必须让权等待，而在该线程退出这个临界区时需要唤醒等待列表中的其他线程。更学术一些，<a href="http://pan.baidu.com/s/1gd3zfrX">《计算机操作系统》</a>中对同步机制准则的归纳（P50）： </p><ol> <li>空闲让进。当无进程处于临界区时，表明临界资源处于空闲状态，应允许一个请求进入临界区的进程立即进入自己的临界区，以有效的利用临界资源。</li> <li>忙则等待。当已有进程进入临界区时，表明临界资源正在被访问，因而其他试图进入临界区的进程必须等待，以保证对临界区资源的互斥访问。</li> <li>有限等待。对要求访问临界资源的进程，应保证在有限时间内能进入自己的临界区，以免陷入&#8220;死等&#8221;状态。</li> <li>让权等待。当进程不能进入自己的临界区时，应该释放处理机，以免进程陷入&#8220;忙等&#8221;状态。</li> </ol> <p>说了那么多，其实对互斥锁很简单，只需要一个标记位，如果该标记位为0，表示没有被占用，因而直接获得锁，然后把该标记位置为1，此时其他线程发现该标记位已经是1，因而需要等待。这里对这个标记位的比较并设值必须是原子操作，而在JDK5以后提供的atomic包里的工具类可以很方便的提供这个原子操作。然而上面的四个准则应该漏了一点，即释放锁的线程（进程）和得到锁的线程（进程）应该是同一个，就像一把钥匙对应一把锁（理想的），所以一个非常简单的Lock类可以这么实现：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SpinLockV1&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;AtomicInteger&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;AtomicInteger(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">volatile</span><span style="color: #000000; ">&nbsp;Thread&nbsp;owner;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;这里owner字段可能存在中间值，不可靠，因而其他线程不可以依赖这个字段的值</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;lock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">state.compareAndSet(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">))&nbsp;{&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Thread.currentThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;unlock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;currentThread&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Thread.currentThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(owner&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;currentThread&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">!</span><span style="color: #000000; ">state.compareAndSet(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;IllegalStateException(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">The&nbsp;lock&nbsp;is&nbsp;not&nbsp;owned&nbsp;by&nbsp;thread:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;currentThread);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;owner&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><p>一个简单的测试方法：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;testLockCorrectly()&nbsp;</span><span style="color: #0000FF; ">throws</span><span style="color: #000000; ">&nbsp;InterruptedException&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;COUNT&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread[]&nbsp;threads&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Thread[COUNT];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SpinLockV1&nbsp;lock&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;SpinLockV1();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddRunner&nbsp;runner&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;AddRunner(lock);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;COUNT;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threads[i]&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Thread(runner,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">thread-</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;i);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threads[i].start();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;COUNT;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threads[i].join();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals(COUNT,&nbsp;runner.getState());<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;AddRunner&nbsp;</span><span style="color: #0000FF; ">implements</span><span style="color: #000000; ">&nbsp;Runnable&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;SpinLockV1&nbsp;lock;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;AddRunner(SpinLockV1&nbsp;lock)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.lock&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;lock;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;run()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.lock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quietSleep(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().getName()&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;state);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">finally</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lock.unlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;getState()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;state;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><p>然而这个SpinLock其实并不需要state这个字段，因为owner的赋值与否也是一种状态，因而可以用它作为一种互斥状态：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;SpinLockV2&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;AtomicReference</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Thread</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;owner&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;AtomicReference</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Thread</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;lock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;Thread&nbsp;currentThread&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Thread.currentThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">owner.compareAndSet(</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">,&nbsp;currentThread))&nbsp;{&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;unlock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;currentThread&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Thread.currentThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">owner.compareAndSet(currentThread,&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;IllegalStateException(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">The&nbsp;lock&nbsp;is&nbsp;not&nbsp;owned&nbsp;by&nbsp;thread:&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;currentThread);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><p>这在操作系统中被定义为整形信号量，然而整形信号量如果没拿到锁会一直处于&#8220;忙等&#8221;状态（没有遵循有限等待和让权等待的准则），因而这种锁也叫Spin Lock，在短暂的等待中它可以提升性能，因为可以减少线程的切换，concurrent包中的Atomic大部分都采用这种机制实现，然而如果需要长时间的等待，&#8220;忙等&#8221;会占用不必要的CPU时间，从而性能会变的很差，这个时候就需要将没有拿到锁的线程放到等待列表中，这种方式在操作系统中也叫记录型信号量，它遵循了让权等待准则（当前没有实现有限等待准则）。在JDK6以后提供了LockSupport.park()/LockSupport.unpark()操作，可以将当前线程放入一个等待列表或将一个线程从这个等待列表中唤醒。然而这个park/unpark的等待列表是一个全局的等待列表，在unpartk的时候还是需要提供需要唤醒的Thread对象，因而我们需要维护自己的等待列表，但是如果我们可以用JDK提供的工具类ConcurrentLinkedQueue，就非常容易实现，如LockSupport文档中给出来的<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/LockSupport.html">代码事例</a>：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;FIFOMutex&nbsp;{<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;AtomicBoolean&nbsp;locked&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;AtomicBoolean(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;Queue</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Thread</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;waiters</span><span style="color: #000000; "> =</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;ConcurrentLinkedQueue</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Thread</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">();<br /><br />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;lock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;wasInterrupted&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;current&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Thread.currentThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waiters.add(current);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Block&nbsp;while&nbsp;not&nbsp;first&nbsp;in&nbsp;queue&nbsp;or&nbsp;cannot&nbsp;acquire&nbsp;lock</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(waiters.peek()&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;current&nbsp;</span><span style="color: #000000; ">||</span><span style="color: #000000; "> </span><span style="color: #000000; ">!</span><span style="color: #000000; ">locked.compareAndSet(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LockSupport.park(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(Thread.interrupted())&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;ignore&nbsp;interrupts&nbsp;while&nbsp;waiting</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wasInterrupted&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waiters.remove();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(wasInterrupted)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;reassert&nbsp;interrupt&nbsp;status&nbsp;on&nbsp;exit</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current.interrupt();<br />&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;unlock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;locked.set(</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LockSupport.unpark(waiters.peek());<br />&nbsp;&nbsp;&nbsp;}<br />&nbsp;}</span></div><p>在该代码事例中，有一个线程等待队列和锁标记字段，每次调用lock时先将当前线程放入这个等待队列中，然后拿出队列头线程对象，如果该线程对象正好是当前线程，并且成功
使用CAS方式设置locked字段（这里需要两个同时满足，因为可能出现一个线程已经从队列中移除了但还没有unlock，此时另一个线程调用lock方法，此时队列头的线程就是第二个线程，然而由于第一个线程还没有unlock或者正在unlock，因而需要使用CAS原子操作来判断是否要park），表示该线程竞争成功，获得锁，否则将当前线程park，这里之所以要放在
while循环中，因为park操作可能无理由返回(<strong>spuriously</strong>)，如文档中给出的描述：<br /></p><fieldset><legend>LockSupport.park()</legend><pre>public static&nbsp;void&nbsp;park(<a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html" title="class in java.lang">Object</a>&nbsp;blocker)</pre>
<div class="block">Disables the current thread for thread scheduling purposes unless the
 permit is available.

 <p>If the permit is available then it is consumed and the call returns
 immediately; otherwise
 the current thread becomes disabled for thread scheduling
 purposes and lies dormant until one of three things happens:

 </p><ul><li>Some other thread invokes <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/LockSupport.html#unpark%28java.lang.Thread%29"><code>unpark</code></a> with the
 current thread as the target; or

 </li><li>Some other thread <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupt%28%29">interrupts</a>
 the current thread; or

 </li><li><strong>The call spuriously (that is, for no reason) returns.
 </strong></li></ul>

 <p>This method does <em>not</em> report which of these caused the
 method to return. Callers should re-check the conditions which caused
 the thread to park in the first place. Callers may also determine,
 for example, the interrupt status of the thread upon return.</p></div>
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>blocker</code> - the synchronization object responsible for this
        thread parking</dd><dt><span class="strong">Since:</span></dt><dd>1.6</dd></dl></fieldset>我在实现自己的类时就被这个&#8220;无理由返回&#8221;坑了好久。对于已经获得锁的线程，将该线程从等待队列中移除，这里由于ConcurrentLinkedQueue是线程安全的，因而能保证每次都是队列头的线程得到锁，因而在得到锁匙将队列头移除。unlock逻辑比较简单，只需要将locked字段打开（设置为false），唤醒（unpark）队列头的线程即可，然后该线程会继续在lock方法的while循环中继续竞争unlocked字段，并将它自己从线程队列中移除表示获得锁成功。当然安全起见，最好在unlock中加入一些验证逻辑，如解锁的线程和加锁的线程需要相同。<br /><br />然而本文的目的是自己实现一个Lock对象，即只使用一些基本的操作，而不使用JDK提供的Atomic类和ConcurrentLinkedQueue。类似的首先我们也需要一个队列存放等待线程队列（公平起见，使用先进先出队列），因而先定义一个Node对象用以构成这个队列：<br /><p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">protected</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Node&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">volatile</span><span style="color: #000000; ">&nbsp;Thread&nbsp;owner;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">volatile</span><span style="color: #000000; ">&nbsp;Node&nbsp;prev;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">volatile</span><span style="color: #000000; ">&nbsp;Node&nbsp;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Node(Thread&nbsp;owner)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.owner&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;owner;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.state&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;INIT;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;Node()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">(Thread.currentThread());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><p>简单起见，队列头是一个起点的placeholder，每个调用lock的线程都先将自己竞争放入这个队列尾，每个队列头后一个线程（Node）即是获得锁的线程，所以我们需要有head Node字段用以快速获取队列头的后一个Node，而tail Node字段用来快速插入新的Node，所以关键在于如何线程安全的构建这个队列，方法还是一样的，使用CAS操作，即CAS方法将自己设置成tail值，然后重新构建这个列表：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">protected</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;enqueue(Node&nbsp;node)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;Node&nbsp;preTail&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;tail;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node.prev&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;preTail;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(compareAndSetTail(preTail,&nbsp;node))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preTail.next&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;node;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;node.prev&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;head;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><p>在当前线程Node以线程安全的方式放入这个队列后，lock实现相对就比较简单了，如果当前Node是的前驱是head，该线程获得锁，否则park当前线程，处理park无理由返回的问题，因而将park放入while循环中（该实现是一个不可重入的实现）：<br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;lock()&nbsp;{</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Put&nbsp;the&nbsp;latest&nbsp;node&nbsp;to&nbsp;a&nbsp;queue&nbsp;first,&nbsp;then&nbsp;check&nbsp;if&nbsp;the&nbsp;it&nbsp;is&nbsp;the&nbsp;first&nbsp;node<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;this&nbsp;way,&nbsp;the&nbsp;list&nbsp;is&nbsp;the&nbsp;only&nbsp;shared&nbsp;resource&nbsp;to&nbsp;deal&nbsp;with</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node&nbsp;node&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Node();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(enqueue(node))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;node.owner;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">&nbsp;(node.prev&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;head)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LockSupport.park(</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">);&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;This&nbsp;may&nbsp;return&nbsp;"spuriously"!!,&nbsp;so&nbsp;put&nbsp;it&nbsp;to&nbsp;while</span><span style="color: #008000; "></span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;node.owner;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><p>unlock的实现需要考虑多种情况，如果当前Node(head.next)有后驱，那么直接unpark该后驱即可；如果没有，表示当前已经没有其他线程在等待队列中，然而在这个判断过程中可能会有其他线程进入，因而需要用CAS的方式设置tail，如果设置失败，表示此时有其他线程进入，因而需要将该新进入的线程unpark从而该新进入的线程在调用park后可以立即返回（这里的CAS和enqueue的CAS都是对tail操作，因而能保证状态一致）：<br /></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;unlock()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node&nbsp;curNode&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;unlockValidate();</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node&nbsp;next&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;curNode.next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(next&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; "></span><span style="color: #000000; "></span><span style="color: #000000; "></span><span style="color: #000000; ">head.next = next;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next.prev&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;head;</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LockSupport.unpark(next.owner);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">!</span><span style="color: #000000; ">compareAndSetTail(curNode,&nbsp;head))&nbsp;{</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000; "><span style="color: #000000; "></span><span style="color: #0000FF; ">while</span><span style="color: #000000; "></span> (curNode.next == null) { } </span><span style="color: #000000; "><span style="color: #000000; "></span><span style="color: #008000; ">//</span><span style="color: #008000; "> Wait until the next available</span></span><br /><span style="color: #000000; "><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Another&nbsp;node&nbsp;queued&nbsp;during&nbsp;the&nbsp;time,&nbsp;so&nbsp;we&nbsp;have&nbsp;to&nbsp;unlock&nbsp;that,&nbsp;or&nbsp;else,&nbsp;this&nbsp;node&nbsp;can&nbsp;never&nbsp;unparked</span><span style="color: #008000; "></span><span style="color: #000000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unlock();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000FF; "></span><span style="color: #000000; ">compareAndSetNext(head,&nbsp;curNode,&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">);</span><span style="color: #000000; "><span style="color: #008000; "> //</span><span style="color: #008000;"> Still use CAS here as the head.next may already been changed</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><p>具体的代码和测试类可以参考查看<a href="https://github.com/dinglevin/levin-learn/tree/master/levin-learn-corejava/src/main/java/levin/learn/corejava/concurrent/locks">这里</a>。<br /></p><p><br />其实直到自己写完这个类后才直到者其实这是一个MCS锁的变种，因而这个实现每个线程park在自身对应的node上，而由前一个线程unpark它；而AbstractQueuedSynchronizer是CLH锁，因为它的park由前驱状态决定，虽然它也是由前一个线程unpark它。具体可以参考<a href="http://coderbee.net/index.php/concurrent/20131115/577">这里</a>。</p><img src ="http://www.blogjava.net/DLevin/aggbug/426723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2015-08-11 06:08 <a href="http://www.blogjava.net/DLevin/archive/2015/08/11/426723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ReferenceCountSet无锁实现</title><link>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Fri, 05 Dec 2014 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/421110.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/421110.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/421110.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 记得很久以前有一次面试被问到如何编写无锁程序，我当时觉得那个面试官脑子进水了，我们确实可以在某些情况下减少锁的使用，但是怎么可能避免呢？当然我现在还是持这种观点，在Java中，你可以有很多方法减少锁的使用(至少在你自己的代码中看起来)：  1.&nbsp;&nbsp;&nbsp;&nbsp; 比如常见的可以使用volatile关键字来保证某个字段在一个线程中的更新对其他线程的可见性；  2.&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/421110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2014-12-06 00:29 <a href="http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Cache系列之Cache概述和Simple Cache</title><link>http://www.blogjava.net/DLevin/archive/2013/10/15/404770.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 15 Oct 2013 15:46:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2013/10/15/404770.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/404770.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2013/10/15/404770.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/404770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/404770.html</trackback:ping><description><![CDATA[前记：最近公司在做的项目完全基于Cache（Gemfire）构建了一个类数据库的系统，自己做的一个小项目里用过Guava的Cache，以前做过的项目中使用过EHCache，既然和Cache那么有缘，那就趁这个机会好好研究一下Java中的Cache库。在Java社区中已经提供了很多Cache库实现，具体可以参考http://www.open-open.com/13.htm，这里只关注自己用到的几个Cache库而且这几个库都比较具有代表性：Guava中提供的Cache是基于单JVM的简单实现；EHCache出自Hibernate，也是基于单JVM的实现，是对单JVM Cache比较完善的实现；而Gemfire则提供了对分布式Cache的完善实现。这一系列的文章主要关注在这几个Cache系统的实现上，因而步探讨关于Cache的好处、何时用Cache等问题，由于他们都是基于内存的Cache，因而也仅局限于这种类型的Cache（说实话，我不知道有没有其他的Cache系统，比如基于文件？囧）。<br />
<br />
记得我最早接触Cache是在大学学计算机组成原理的时候，由于CPU的速度要远大于内存的读取速度，为了提高CPU的效率，CPU会在内部提供缓存区，该缓存区的读取速度和CPU的处理速度类似，CPU可以直接从缓存区中读取数据，从而解决CPU的处理速度和内存读取速度不匹配的问题。缓存之所以能解决这个问题是基于程序的局部性原理，即&#8221;程序在执行时呈现出局部性规律，即在一段时间内，整个程序的执行仅限于程序中的某一部分。相应地，执行所访问的存储空间也局限于某个内存区域。局部性原理又表现为：时间局部性和空间局部性。时间局部性是指如果程序中的某条指令一旦执行，则不久之后该指令可能再次被执行；如果某数据被访问，则不久之后该数据可能再次被访问。空间局部性是指一旦程序访问了某个存储单元，则不久之后。其附近的存储单元也将被访问。&#8221;在实际工作中，CPU先向缓存区读取数据，如果缓存区已存在，则读取缓存中的数据（命中），否则（失效），将内存中相应数据块载入缓存中，以提高接下来的访问速度。由于成本和CPU大小的限制，CPU只能提供有限的缓存区，因而缓存区的大小是衡量CPU性能的重要指标之一。<br />
<br />
使用缓存，在CPU向内存更新数据时需要处理一个问题（写回策略问题），即CPU在更新数据时只更新缓存的数据（write back，写回，当缓存需要被替换时才将缓存中更新的值写回内存），还是CPU在更新数据时同时更新缓存中和内存中的数据（write through，写通）。在写回策略中，为了减少内存写操作，缓存块通常还设有一个脏位（dirty bit），用以标识该块在被载入之后是否发生过更新。如果一个缓存块在被置换回内存之前从未被写入过，则可以免去回写操作；写回的优点是节省了大量的写操作。这主要是因为，对一个数据块内不同单元的更新仅需一次写操作即可完成。这种内存带宽上的节省进一步降低了能耗，因此颇适用于嵌入式系统。写通策略由于要经常和内存交互（有些CPU设计会在中间提供写缓冲器以缓解性能），因而性能较差，但是它实现简单，而且能简单的维持数据一致性。<br />
<br />
在软件的缓存系统中，一般是为了解决内存的访问速率和磁盘、网络、数据库（属于磁盘或网络访问，单独列出来因为它的应用比较广泛）等访问速率不匹配的问题（对于内存缓存系统来说）。但是由于内存大小和成本的限制，我们又不能把所有的数据先加载进内存来。因而如CPU中的缓存，我们只能先将一部分数据保存在缓存中。此时，对于缓存，我们一般要解决如下需求：
<ol style="margin-top:1px">
     <li>使用给定Key从Cache中读取Value值。CPU是通过内存地址来定位内存已获取相应内存中的值，类似的在软件Cache中，需要通过某个Key值来标识相关的值。因而可以简单的认为软件中的Cache是一个存储键值对的Map，比如Gemfire中的Region就继承自Map，只是Cache的实现更加复杂。</li>
     <li>当给定的Key在当前Cache不存在时，程序员可以通过指定相应的逻辑从其他源（如数据库、网络等源）中加载该Key对应的Value值，同时将该值返回。在CPU中，基于程序局部性原理，一般是默认的加载接下来的一段内存块，然而在软件中，不同的需求有不同的加载逻辑，因而需要用户自己指定对应的加载逻辑，而且一般来说也很难预知接下来要读取的数据，所以只能一次只加载一条纪录（对可预知的场景下当然可以批量加载数据，只是此时需要权衡当前操作的响应时间问题）。</li>
     <li>可以向Cache中写入Key－Value键值对（新增的纪录或对原有的键值对的更新）。就像CPU的写回策略中有写回和写通策略，有些Cache系统提供了写通接口。如果没有提供写通接口，程序员需要额外的逻辑处理写通策略。也可以如CPU中的Cache一样，只当相应的键值对移出Cache以后，再将值写回到数据源，可以提供一个标记位以决定要不要写回（不过感觉这种实现比较复杂，代码的的耦合度也比较高，如果为提升写的速度，采用异步写回即可，为防止数据丢失，可以使用Queue来存储）。</li>
     <li>将给定Key的键值对移出Cache（或给定多个Key以批量移除，甚至清除整个Cache）。</li>
     <li>配置Cache的最大使用率，当Cache超过该使用率时，可配置溢出策略
     <ol><li>直接移除溢出的键值对。在移除时决定是否要写回已更新的数据到数据源。</li><li>将溢出的溢出的键值对写到磁盘中。在写磁盘时需要解决如何序列化键值对，如何存储序列化后的数据到磁盘中，如何布局磁盘存储，如何解决磁盘碎片问题，如何从磁盘中找回相应的键值对，如何读取磁盘中的数据并方序列化，如何处理磁盘溢出等问题。</li><li>在溢出策略中，除了如何处理溢出的键值对问题，还需要处理如何选择溢出的键值对问题。这有点类似内存的页面置换算法（其实内存也可以看作是对磁盘的Cache），一般使用的算法有：先进先出（FIFO）、最近最少使用（LRU）、最少使用（LFU）、Clock置换（类LRU）、工作集等算法。</li></ol><ul>
     </ul>
     </li>
     <li>对Cache中的键值对，可以配置其生存时间，以处理某些键值对在长时间不被使用，但是又没能溢出的问题（因为溢出策略的选择或者Cache没有到溢出阶段），以提前释放内存。</li>
     <li>对某些特定的键值对，我们希望它能一直留在内存中不被溢出，有些Cache系统提供PIN配置（动态或静态），以确保该键值对不会被溢出。</li>
     <li>提供Cache状态、命中率等统计信息，如磁盘大小、Cache大小、平均查询时间、每秒查询次数、内存命中次数、磁盘命中次数等信息。</li>
     <li>提供注册Cache相关的事件处理器，如Cache的创建、Cache的销毁、一条键值对的添加、一条键值对的更新、键值对溢出等事件。</li>
     <li>由于引入Cache的目的就是为了提升程序的读写性能，而且一般Cache都需要在多线程环境下工作，因而在实现时一般需要保证线程安全，以及提供高效的读写性能。</li>
</ol>
在Java中，Map是最简单的Cache，为了高效的在多线程环境中使用，可以使用ConcurrentHashMap，这也正是我之前参与的一个项目中最开始的实现（后来引入EHCache）。为了语意更加清晰、保持接口的简单，下面我实现了一个基于Map的最简单的Cache系统，用以演示Cache的基本使用方式。用户可以向它提供数据、查询数据、判断给定Key的存在性、移除给定的Key(s)、清除整个Cache等操作。以下是Cache的接口定义。<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;Cache&lt;K,&nbsp;V&gt;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;String&nbsp;getName();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;V&nbsp;get(K&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;getAll(Iterator&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K&gt;&nbsp;keys);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isPresent(K&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;putAll(Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;entries);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidate(K&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidateAll(Iterator&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K&gt;&nbsp;keys);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidateAll();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isEmpty();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;size();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;asMap();<br />
}</div>
这个简单的Cache实现只是对HashMap的封装，之所以选择HashMap而不是ConcurrentHashMap是因为在ConcurrentHashMap无法实现getAll()方法；并且这里所有的操作我都加锁了，因而也不需要ConcurrentHashMap来保证线程安全问题；为了提升性能，我使用了读写锁，以提升并发查询性能。因为代码比较简单，所以把所有代码都贴上了（懒得整理了。。。。）。<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;CacheImpl&lt;K,&nbsp;V&gt;&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;Cache&lt;K,&nbsp;V&gt;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;String&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;HashMap&lt;K,&nbsp;V&gt;&nbsp;cache;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;ReadWriteLock&nbsp;lock&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ReentrantReadWriteLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;Lock&nbsp;readLock&nbsp;=&nbsp;lock.readLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;Lock&nbsp;writeLock&nbsp;=&nbsp;lock.writeLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;CacheImpl(String&nbsp;name)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>.name&nbsp;=&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;HashMap&lt;K,&nbsp;V&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;CacheImpl(String&nbsp;name,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;initialCapacity)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">this</span>.name&nbsp;=&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;HashMap&lt;K,&nbsp;V&gt;(initialCapacity);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;String&nbsp;getName()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;V&nbsp;get(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cache.get(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;getAll(Iterator&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K&gt;&nbsp;keys)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map&lt;K,&nbsp;V&gt;&nbsp;map&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;HashMap&lt;K,&nbsp;V&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;K&gt;&nbsp;noEntryKeys&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ArrayList&lt;K&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(keys.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K&nbsp;key&nbsp;=&nbsp;keys.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(isPresent(key))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;cache.get(key));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;noEntryKeys.add(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!noEntryKeys.isEmpty())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throw</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CacheEntriesNotExistException(<span style="color: #0000FF; ">this</span>,&nbsp;noEntryKeys);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;map;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isPresent(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cache.containsKey(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(key,&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;putAll(Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;entries)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.putAll(entries);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidate(K&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!isPresent(key))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throw</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CacheEntryNotExistsException(<span style="color: #0000FF; ">this</span>,&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.remove(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidateAll(Iterator&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K&gt;&nbsp;keys)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;K&gt;&nbsp;noEntryKeys&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ArrayList&lt;K&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(keys.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K&nbsp;key&nbsp;=&nbsp;keys.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!isPresent(key))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;noEntryKeys.add(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!noEntryKeys.isEmpty())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throw</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CacheEntriesNotExistException(<span style="color: #0000FF; ">this</span>,&nbsp;noEntryKeys);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(keys.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K&nbsp;key&nbsp;=&nbsp;keys.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invalidate(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;invalidateAll()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;size()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cache.size();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;clear()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writeLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;asMap()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ConcurrentHashMap&lt;K,&nbsp;V&gt;(cache);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isEmpty()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.lock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cache.isEmpty();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">finally</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;readLock.unlock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}</div>
其简单的使用用例如下：
<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp; @Test<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;testCacheSimpleUsage()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Book&nbsp;uml&nbsp;=&nbsp;bookFactory.createUMLDistilled();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Book&nbsp;derivatives&nbsp;=&nbsp;bookFactory.createDerivatives();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;umlBookISBN&nbsp;=&nbsp;uml.getIsbn();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;derivativesBookISBN&nbsp;=&nbsp;derivatives.getIsbn();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cache&lt;String,&nbsp;Book&gt;&nbsp;cache&nbsp;=&nbsp;cacheFactory.create("book-cache");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(umlBookISBN,&nbsp;uml);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cache.put(derivativesBookISBN,&nbsp;derivatives);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Book&nbsp;fetchedBackUml&nbsp;=&nbsp;cache.get(umlBookISBN);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fetchedBackUml);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Book&nbsp;fetchedBackDerivatives&nbsp;=&nbsp;cache.get(derivativesBookISBN);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fetchedBackDerivatives);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div><img src ="http://www.blogjava.net/DLevin/aggbug/404770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2013-10-15 23:46 <a href="http://www.blogjava.net/DLevin/archive/2013/10/15/404770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Map deserialize from String</title><link>http://www.blogjava.net/DLevin/archive/2011/09/20/359078.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 20 Sep 2011 07:54:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/09/20/359078.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/359078.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/09/20/359078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/359078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/359078.html</trackback:ping><description><![CDATA[<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span><img id="Codehighlighter1_28_1820_Open_Image" onclick="this.style.display='none'; Codehighlighter1_28_1820_Open_Text.style.display='none'; Codehighlighter1_28_1820_Closed_Image.style.display='inline'; Codehighlighter1_28_1820_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_28_1820_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_28_1820_Closed_Text.style.display='none'; Codehighlighter1_28_1820_Open_Image.style.display='inline'; Codehighlighter1_28_1820_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;MapDeserialize&nbsp;</span><span id="Codehighlighter1_28_1820_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_28_1820_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img id="Codehighlighter1_73_765_Open_Image" onclick="this.style.display='none'; Codehighlighter1_73_765_Open_Text.style.display='none'; Codehighlighter1_73_765_Closed_Image.style.display='inline'; Codehighlighter1_73_765_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_73_765_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_73_765_Closed_Text.style.display='none'; Codehighlighter1_73_765_Open_Image.style.display='inline'; Codehighlighter1_73_765_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id="Codehighlighter1_73_765_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_73_765_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;map&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HashMap</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br /></span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(</span><span style="color: #000000">"</span><span style="color: #000000">key1</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">value1</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(</span><span style="color: #000000">"</span><span style="color: #000000">key2</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(</span><span style="color: #000000">"</span><span style="color: #000000">key3</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">""</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(map);<br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;emptyMap&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HashMap</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(emptyMap);<br /></span><span style="color: #008080">12</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">13</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MapDeserialize&nbsp;deserialize&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;MapDeserialize();<br /></span><span style="color: #008080">14</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">{key3=,&nbsp;key2=null,&nbsp;key1=value1}</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #008080">15</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">{}</span><span style="color: #000000">"</span><span style="color: #000000">;<br /></span><span style="color: #008080">16</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;map1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;deserialize.str2Map(str1);<br /></span><span style="color: #008080">17</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">map1:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;map1);<br /></span><span style="color: #008080">18</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;map2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;deserialize.str2Map(str2);<br /></span><span style="color: #008080">19</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">map2:&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;map2);<br /></span><span style="color: #008080">20</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">21</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">22</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;We&nbsp;are&nbsp;assuming&nbsp;that&nbsp;the&nbsp;str&nbsp;is&nbsp;generated&nbsp;by&nbsp;map.toString(),&nbsp;so&nbsp;the&nbsp;str&nbsp;will&nbsp;be&nbsp;something&nbsp;like:<br /></span><span style="color: #008080">23</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;'{key3=,&nbsp;key2=null,&nbsp;key1=value1}'&nbsp;or&nbsp;'{}'</span><span style="color: #008000"><br /></span><span style="color: #008080">24</span><span style="color: #008000"><img id="Codehighlighter1_975_1818_Open_Image" onclick="this.style.display='none'; Codehighlighter1_975_1818_Open_Text.style.display='none'; Codehighlighter1_975_1818_Closed_Image.style.display='inline'; Codehighlighter1_975_1818_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_975_1818_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_975_1818_Closed_Text.style.display='none'; Codehighlighter1_975_1818_Open_Image.style.display='inline'; Codehighlighter1_975_1818_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;str2Map(String&nbsp;str)&nbsp;</span><span id="Codehighlighter1_975_1818_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_975_1818_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">25</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Map</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;map&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HashMap</span><span style="color: #000000">&lt;</span><span style="color: #000000">String,&nbsp;String</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br /></span><span style="color: #008080">26</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;The&nbsp;parameters&nbsp;map&nbsp;is&nbsp;empty</span><span style="color: #008000"><br /></span><span style="color: #008080">27</span><span style="color: #008000"><img id="Codehighlighter1_1146_1180_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1146_1180_Open_Text.style.display='none'; Codehighlighter1_1146_1180_Closed_Image.style.display='inline'; Codehighlighter1_1146_1180_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1146_1180_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1146_1180_Closed_Text.style.display='none'; Codehighlighter1_1146_1180_Open_Image.style.display='inline'; Codehighlighter1_1146_1180_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #000000">"</span><span style="color: #000000">{}</span><span style="color: #000000">"</span><span style="color: #000000">.equals(str)&nbsp;</span><span style="color: #000000">||</span><span style="color: #000000">&nbsp;str&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">||</span><span style="color: #000000">&nbsp;str.length()&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1146_1180_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1146_1180_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">28</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;map;<br /></span><span style="color: #008080">29</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">30</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">31</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Remove&nbsp;the&nbsp;'{'&nbsp;prefix&nbsp;and&nbsp;'}'&nbsp;suffix</span><span style="color: #008000"><br /></span><span style="color: #008080">32</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;str.substring(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;str.length()&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">);<br /></span><span style="color: #008080">33</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;entries&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;str.split(</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">34</span><span style="color: #000000"><img id="Codehighlighter1_1368_1783_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1368_1783_Open_Text.style.display='none'; Codehighlighter1_1368_1783_Closed_Image.style.display='inline'; Codehighlighter1_1368_1783_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1368_1783_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1368_1783_Closed_Text.style.display='none'; Codehighlighter1_1368_1783_Open_Image.style.display='inline'; Codehighlighter1_1368_1783_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">(String&nbsp;entry&nbsp;:&nbsp;entries)&nbsp;</span><span id="Codehighlighter1_1368_1783_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1368_1783_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">35</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;pair&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;entry.split(</span><span style="color: #000000">"</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">);<br /></span><span style="color: #008080">36</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;key&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;pair[</span><span style="color: #000000">0</span><span style="color: #000000">].trim();<br /></span><span style="color: #008080">37</span><span style="color: #000000"><img id="Codehighlighter1_1490_1538_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1490_1538_Open_Text.style.display='none'; Codehighlighter1_1490_1538_Closed_Image.style.display='inline'; Codehighlighter1_1490_1538_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1490_1538_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1490_1538_Closed_Text.style.display='none'; Codehighlighter1_1490_1538_Open_Image.style.display='inline'; Codehighlighter1_1490_1538_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(pair.length&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1490_1538_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1490_1538_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">38</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;</span><span style="color: #000000">""</span><span style="color: #000000">);<br /></span><span style="color: #008080">39</span><span style="color: #000000"><img id="Codehighlighter1_1545_1773_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1545_1773_Open_Text.style.display='none'; Codehighlighter1_1545_1773_Closed_Image.style.display='inline'; Codehighlighter1_1545_1773_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1545_1773_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1545_1773_Closed_Text.style.display='none'; Codehighlighter1_1545_1773_Open_Image.style.display='inline'; Codehighlighter1_1545_1773_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1545_1773_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1545_1773_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">40</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;value&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;pair[</span><span style="color: #000000">1</span><span style="color: #000000">].trim();<br /></span><span style="color: #008080">41</span><span style="color: #000000"><img id="Codehighlighter1_1635_1693_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1635_1693_Open_Text.style.display='none'; Codehighlighter1_1635_1693_Closed_Image.style.display='inline'; Codehighlighter1_1635_1693_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1635_1693_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1635_1693_Closed_Text.style.display='none'; Codehighlighter1_1635_1693_Open_Image.style.display='inline'; Codehighlighter1_1635_1693_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(</span><span style="color: #000000">"</span><span style="color: #000000">null</span><span style="color: #000000">"</span><span style="color: #000000">.equals(value))&nbsp;</span><span id="Codehighlighter1_1635_1693_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1635_1693_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">42</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">);<br /></span><span style="color: #008080">43</span><span style="color: #000000"><img id="Codehighlighter1_1700_1759_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1700_1759_Open_Text.style.display='none'; Codehighlighter1_1700_1759_Closed_Image.style.display='inline'; Codehighlighter1_1700_1759_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"><img id="Codehighlighter1_1700_1759_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1700_1759_Closed_Text.style.display='none'; Codehighlighter1_1700_1759_Open_Image.style.display='inline'; Codehighlighter1_1700_1759_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1700_1759_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_1700_1759_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">44</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;value);<br /></span><span style="color: #008080">45</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">46</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">47</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">48</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080">49</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;map;<br /></span><span style="color: #008080">50</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br /></span><span style="color: #008080">51</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span></div>这段代码貌似没什么价值，只是保留着，以后再遇到相应的情况，可以再做改进。 <img src ="http://www.blogjava.net/DLevin/aggbug/359078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-09-20 15:54 <a href="http://www.blogjava.net/DLevin/archive/2011/09/20/359078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>StopWatch类</title><link>http://www.blogjava.net/DLevin/archive/2011/07/08/353922.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Fri, 08 Jul 2011 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/08/353922.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/353922.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/08/353922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/353922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/353922.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp;&nbsp;1/**&nbsp;*//**&nbsp;&nbsp;2&nbsp;*&nbsp;在C#中提供了一个专门用于简单测试运行时间的类StopWatch，&nbsp;&nbsp;3&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2011/07/08/353922.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/353922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-08 11:05 <a href="http://www.blogjava.net/DLevin/archive/2011/07/08/353922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>