﻿<?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-少年阿宾-随笔分类-HighConcurrency</title><link>http://www.blogjava.net/stevenjohn/category/53428.html</link><description>那些青春的岁月</description><language>zh-cn</language><lastBuildDate>Thu, 23 May 2013 07:30:54 GMT</lastBuildDate><pubDate>Thu, 23 May 2013 07:30:54 GMT</pubDate><ttl>60</ttl><item><title>请问java中的lock和synchronized区别是什么？</title><link>http://www.blogjava.net/stevenjohn/archive/2013/05/23/399651.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 23 May 2013 04:39:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/05/23/399651.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/399651.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/05/23/399651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/399651.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/399651.html</trackback:ping><description><![CDATA[<pre id="recommend-content-1121378047" accuse="aContent"  mb-10"="" style="margin-top: 0px; margin-bottom: 10px; padding: 0px; font-family: arial, 'courier new', courier, 宋体, monospace; white-space: pre-wrap; word-wrap: break-word; color: #333333; line-height: 24px; background-color: #f1fedd;">1、ReentrantLock 拥有Synchronized相同的并发性和内存语义，此外还多了 锁投票，定时锁等候和中断锁等候<br />     线程A和B都要获取对象O的锁定，假设A获取了对象O锁，B将等待A释放对O的锁定，<br />     如果使用 synchronized ，如果A不释放，B将一直等下去，不能被中断<br />     如果 使用ReentrantLock，如果A不释放，可以使B在等待了足够长的时间以后，中断等待，而干别的事情<br /> <br />    ReentrantLock获取锁定与三种方式：<br />    a)  lock(), 如果获取了锁立即返回，如果别的线程持有锁，当前线程则一直处于休眠状态，直到获取锁<br />    b) tryLock(), 如果获取了锁立即返回true，如果别的线程正持有锁，立即返回false；<br />    c)tryLock(long timeout,TimeUnit unit)，   如果获取了锁定立即返回true，如果别的线程正持有锁，会等待参数给定的时间，在等待的过程中，如果获取了锁定，就返回true，如果等待超时，返回false；<br />    d) lockInterruptibly:如果获取了锁定立即返回，如果没有获取锁定，当前线程处于休眠状态，直到或者锁定，或者当前线程被别的线程中断<br /> <br />2、synchronized是在JVM层面上实现的，不但可以通过一些监控工具监控synchronized的锁定，而且在代码执行时出现异常，JVM会自动释放锁定，但是使用Lock则不行，lock是通过代码实现的，要保证锁定一定会被释放，就必须将unLock()放到finally{}中<br /> <br />3、在资源竞争不是很激烈的情况下，Synchronized的性能要优于ReetrantLock，但是在资源竞争很激烈的情况下，Synchronized的性能会下降几十倍，但是ReetrantLock的性能能维持常态；</pre><img src ="http://www.blogjava.net/stevenjohn/aggbug/399651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-05-23 12:39 <a href="http://www.blogjava.net/stevenjohn/archive/2013/05/23/399651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java多线程 BlockingQueue深入分析</title><link>http://www.blogjava.net/stevenjohn/archive/2013/05/13/399219.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 13 May 2013 08:54:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/05/13/399219.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/399219.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/05/13/399219.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/399219.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/399219.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 1)ArrayBlockingQueue:规定大小的BlockingQueue,其构造函数必须带一个int参数来指明其大小.其所含的对象是以FIFO(先入先出)顺序排序的. 
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)LinkedBlockingQueue:大小不定的BlockingQueue,若其构造函数带一个规定大小的参数,生成的BlockingQueue有大小限制,若不带大小参数,所生成的BlockingQueue的大小由Integer.MAX_VALUE来决定.其所含的对象是以FIFO(先入先出)顺序排序的</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)PriorityBlockingQueue:类似于LinkedBlockQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数的Comparator决定的顺序.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4)SynchronousQueue:特殊的BlockingQueue,对其的操作必须是放和取交替完成的,<span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 28px; display: inline !important; font: 14px/25px Arial, Helvetica, simsun, u5b8bu4f53; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">是之前提过的</span><span style="text-align: left; widows: 2; text-transform: none; background-color: rgb(255,255,255); text-indent: 28px; display: inline !important; font: 14px/25px Arial, Helvetica, simsun, u5b8bu4f53; white-space: normal; orphans: 2; float: none; letter-spacing: normal; color: rgb(51,51,51); word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">BlockingQueue的又一实现。它给我们提供了在线程之间交换单一元素的极轻量级方法.</span></p>
<p>&nbsp;&nbsp;&nbsp; 其中LinkedBlockingQueue和ArrayBlockingQueue比较起来,它们背后所用的数据结构不一样,导致LinkedBlockingQueue的数据吞吐量要大于ArrayBlockingQueue,但在线程数量很大时其性能的可预见性低于ArrayBlockingQueue.&nbsp;</p>
<p>&nbsp;<a href="http://www.2cto.com/kf/201212/175028.html">http://www.2cto.com/kf/201212/175028.html</a></p><img src ="http://www.blogjava.net/stevenjohn/aggbug/399219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-05-13 16:54 <a href="http://www.blogjava.net/stevenjohn/archive/2013/05/13/399219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 高并发 基础知识 </title><link>http://www.blogjava.net/stevenjohn/archive/2013/05/06/398876.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Mon, 06 May 2013 10:33:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/05/06/398876.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/398876.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/05/06/398876.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/398876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/398876.html</trackback:ping><description><![CDATA[<h2 style="font-family: Times" sizset="48" sizcache="3"><a name="t1"></a>锁:</h2>
<div>
<ol><li>内置锁 (监视器锁): 每个java对象都可以做一个实现同步的锁,这些锁被成为内置锁. 获得锁的唯一途径就是进入有这个锁保护的代码块或方法</li><li>重入锁: 由于内置锁是可重入的,因此如果某个线程试图获得一个以已经由他自己持有的锁, 那么这个请求就会成功.重入意味着获取锁的操作粒度是"线程",而不是"调用"</li></ol><span style="white-space: pre"></span></div>
<div><span style="white-space: pre"></span></div>
<h2 style="font-family: Times" sizset="49" sizcache="3"><a name="t2"></a>volatile 使用条件(<span style="color: rgb(255,102,102)">必须同时满足所有条件</span>):</h2>
<div>
<ol><li>对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值</li><li>该变量不会与其他状态变量一起纳入不变性条件中</li><li>在访问变量时间不需要加锁</li></ol></div>
<h2 style="font-family: Times" sizset="50" sizcache="3"><a name="t3"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="51" sizcache="3"><a name="t4"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="52" sizcache="3"><a name="t5"></a>高并发术语</h2>
<address><span style="font-weight: normal"><br /></span></address>
<address><span style="font-weight: normal"><br /></span></address>
<address><span style="font-weight: normal"></span>
<table style="line-height: 19px; font-family: Lucida,'Lucida Grande',Tahoma,sans-serif; color: rgb(0,0,0)" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">术语</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">英文单词</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">描述</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial"><strong>比较并交换</strong></span></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">Compare and Swap</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CAS操作需要输入两个数值，一个旧值（期望操作前的值）和一个新值，在操作期间先比较下旧值有没有发生变化，如果没有发生变化，才交换成新值，发生了变化则不交换</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong><span style="text-align: center; font-family: Arial">CPU流水线</span></strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CPU pipeline</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CPU流水线的工作方式就象工业生产上的装配流水线，在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线，然后将一条X86指令分成5~6步后再由这些电路单元分别执行，这样就能实现在一个CPU时钟周期完成一条指令，因此提高CPU的运算速度</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial"><strong>内存顺序冲突</strong></span></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">Memory order violation</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">内存顺序冲突一般是由假共享引起，假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效，当出现这个内存顺序冲突时，CPU必须清空流水线</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>共享变量</strong></span></p></td>
<td valign="top" width="155"><span style="font-size: 12px"><br /></span></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">在多个线程之间能够被共享的变量被称为共享变量。共享变量包括所有的实例变量，静态变量和数组元素。他们都被存放在堆内存中，Volatile只作用于共享变量。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>内存屏障</strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Memory Barriers</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">是一组处理器指令，用于实现对内存操作的顺序限制。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>缓冲行</strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Cache line</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个缓存线，需要使用多个主内存读周期。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">原子操作</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Atomic operations</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">不可中断的一个或一系列操作。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">缓存行填充</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">cache line fill</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">当处理器识别到从内存中读取操作数是可缓存的，处理器读取整个缓存行到适当的缓存（L1，L2，L3的或所有）</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">缓存命中</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">cache hit</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时，处理器从缓存中读取操作数，而不是从内存。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">写命中</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">write hit</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">当处理器将操作数写回到一个内存缓存的区域时，它首先会检查这个缓存的内存地址是否在缓存行中，如果存在一个有效的缓存行，则处理器将这个操作数写回到缓存，而不是写回到内存，这个操作被称为写命中。</span></p></td></tr></tbody></table><br /></address>
<h2 style="font-family: Times" sizset="53" sizcache="3"><a name="t6"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="54" sizcache="3"><a name="t7"></a>synchronized</h2>
<h2 style="font-family: Times" sizset="55" sizcache="3"><a name="t8"></a>volatile<br /></h2>
<h2 style="font-family: Times" sizset="56" sizcache="3"><a name="t9"></a>concurrent&nbsp;</h2>
<p style="font-family: Times; font-size: 14px"></p>
<p style="font-family: Times; font-size: 14px">在并发编程中很常用的实用工具类。此包包括了几个小的、已标准化的可扩展框架，以及一些提供有用功能的类，没有这些类，这些功能会很难实现或实现起来冗长乏味。下面简要描述主要的组件。另请参阅&nbsp;<tt>locks</tt>&nbsp;和&nbsp;<tt>atomic</tt>&nbsp;包。</p>
<h2 style="font-family: Times" sizset="57" sizcache="3"><a name="t10"></a>执行程序</h2><span style="font-family: Times; font-size: 14px">接口。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Executor</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个简单的标准化接口，用于定义类似于线程的自定义子系统，包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同，可能在新创建的线程中，现有的任务执行线程中，或者调用&nbsp;</span><tt style="font-size: 14px">execute()</tt><span style="font-family: Times; font-size: 14px">&nbsp;的线程中执行任务，并且可能顺序或并发执行。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>ExecutorService</code></a><span style="font-family: Times; font-size: 14px">&nbsp;提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排，并允许受控制的关闭。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>ScheduledExecutorService</code></a><span style="font-family: Times; font-size: 14px">&nbsp;子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法，可执行由&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Callable</code></a><span style="font-family: Times; font-size: 14px">&nbsp;表示的任何函数，结果类似于&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.lang 中的接口" href=""><code>Runnable</code></a><span style="font-family: Times; font-size: 14px">。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Future</code></a><span style="font-family: Times; font-size: 14px">&nbsp;返回函数的结果，允许确定执行是否完成，并提供取消执行的方法。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>RunnableFuture</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是拥有&nbsp;</span><tt style="font-size: 14px">run</tt><span style="font-family: Times; font-size: 14px">&nbsp;方法的 Future，</span><tt style="font-size: 14px">run</tt><span style="font-family: Times; font-size: 14px">&nbsp;方法执行时将设置其结果。</span> 
<p style="font-family: Times; font-size: 14px" sizset="65" sizcache="3"><strong>实现。</strong>类&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ThreadPoolExecutor</code></a>&nbsp;和&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ScheduledThreadPoolExecutor</code></a>&nbsp;提供可调的、灵活的线程池。<a title="java.util.concurrent 中的类" href=""><code>Executors</code></a>&nbsp;类提供大多数 Executor 的常见类型和配置的工厂方法，以及使用它们的几种实用工具方法。其他基于 Executor 的实用工具包括具体类&nbsp;<a title="java.util.concurrent 中的类" href=""><code>FutureTask</code></a>，它提供 Future 的常见可扩展实现，以及&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ExecutorCompletionService</code></a>，它有助于协调对异步任务组的处理。</p>
<h2 style="font-family: Times" sizset="70" sizcache="3"><a name="t11"></a>队列</h2><span style="font-family: Times; font-size: 14px">java.util.concurrent&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentLinkedQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>BlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;接口，该接口定义了 put 和 take 的阻塞版本：</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>LinkedBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ArrayBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>SynchronousQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>PriorityBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>DelayQueue</code></a><span style="font-family: Times; font-size: 14px">。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>BlockingDeque</code></a><span style="font-family: Times; font-size: 14px">&nbsp;接口扩展&nbsp;</span><tt style="font-size: 14px">BlockingQueue</tt><span style="font-family: Times; font-size: 14px">，以支持 FIFO 和 LIFO（基于堆栈）操作。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>LinkedBlockingDeque</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供一个实现。</span> 
<h2 style="font-family: Times" sizset="80" sizcache="3"><a name="t12"></a>计时</h2><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的枚举" href=""><code>TimeUnit</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类为指定和控制基于超时的操作提供了多重粒度（包括纳秒级）。该包中的大多数类除了包含不确定的等待之外，还包含基于超时的操作。在使用超时的所有情况中，超时指定了在表明已超时前该方法应该等待的最少时间。在超时发生后，实现会&#8220;尽力&#8221;检测超时。但是，在检测超时与超时之后再次实际执行线程之间可能要经过不确定的时间。接受超时期参数的所有方法将小于等于 0 的值视为根本不会等待。要&#8220;永远&#8221;等待，可以使用&nbsp;</span><tt style="font-size: 14px">Long.MAX_VALUE</tt><span style="font-family: Times; font-size: 14px">&nbsp;值。</span> 
<h2 style="font-family: Times" sizset="82" sizcache="3"><a name="t13"></a>同步器</h2><span style="font-family: Times; font-size: 14px">四个类可协助实现常见的专用同步语句。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>Semaphore</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个经典的并发工具。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CountDownLatch</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个极其简单但又极其常用的实用工具，用于在保持给定数目的信号、事件或条件前阻塞执行。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CyclicBarrier</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个可重置的多路同步点，在某些并行编程风格中很有用。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>Exchanger</code></a><span style="font-family: Times; font-size: 14px">&nbsp;允许两个线程在 collection 点交换对象，它在多流水线设计中是有用的。</span> 
<h2 style="font-family: Times" sizset="87" sizcache="3"><a name="t14"></a>并发 Collection</h2><span style="font-family: Times; font-size: 14px">除队列外，此包还提供了设计用于多线程上下文中的 Collection 实现：</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentHashMap</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentSkipListMap</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentSkipListSet</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CopyOnWriteArrayList</code></a><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CopyOnWriteArraySet</code></a><span style="font-family: Times; font-size: 14px">。当期望许多线程访问一个给定 collection 时，</span><tt style="font-size: 14px">ConcurrentHashMap</tt><span style="font-family: Times; font-size: 14px">&nbsp;通常优于同步的&nbsp;</span><tt style="font-size: 14px">HashMap</tt><span style="font-family: Times; font-size: 14px">，</span><tt style="font-size: 14px">ConcurrentSkipListMap</tt><span style="font-family: Times; font-size: 14px">&nbsp;通常优于同步的&nbsp;</span><tt style="font-size: 14px">TreeMap</tt><span style="font-family: Times; font-size: 14px">。当期望的读数和遍历远远大于列表的更新数时，</span><tt style="font-size: 14px">CopyOnWriteArrayList</tt><span style="font-family: Times; font-size: 14px">&nbsp;优于同步的&nbsp;</span><tt style="font-size: 14px">ArrayList</tt><span style="font-family: Times; font-size: 14px">。</span> 
<p style="font-family: Times; font-size: 14px" sizset="93" sizcache="3">此包中与某些类一起使用的&#8220;Concurrent&amp;rdquo前缀;是一种简写，表明与类似的&#8220;同步&#8221;类有所不同。例如，<tt>java.util.Hashtable</tt>&nbsp;和<tt>Collections.synchronizedMap(new HashMap())</tt>&nbsp;是同步的，但&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ConcurrentHashMap</code></a>&nbsp;则是&#8220;并发的&#8221;。并发 collection 是线程安全的，但是不受单个排他锁的管理。在 ConcurrentHashMap 这一特定情况下，它可以安全地允许进行任意数目的并发读取，以及数目可调的并发写入。需要通过单个锁不允许对 collection 的所有访问时，&#8220;同步&#8221;类是很有用的，其代价是较差的可伸缩性。在期望多个线程访问公共 collection 的其他情况中，通常&#8220;并发&#8221;版本要更好一些。当 collection 是未共享的，或者仅保持其他锁时 collection 是可访问的情况下，非同步 collection 则要更好一些。</p>
<p style="font-family: Times; font-size: 14px" sizset="94" sizcache="3">大多数并发 Collection 实现（包括大多数 Queue）与常规的 java.util 约定也不同，因为它们的迭代器提供了<em>弱一致的</em>，而不是快速失败的遍历。弱一致的迭代器是线程安全的，但是在迭代时没有必要冻结 collection，所以它不一定反映自迭代器创建以来的所有更新。<a id="MemoryVisibility" name="MemoryVisibility"></a></p>
<h2 style="font-family: Times" sizset="95" sizcache="3"><a name="t15"></a><a id="MemoryVisibility" name="MemoryVisibility">内存一致性属性</a></h2><a style="font-family: Times; font-size: 14px" id="MemoryVisibility" name="MemoryVisibility"></a><a style="font-family: Times; font-size: 14px" href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">Java Language Specification 第 17 章</a><span style="font-family: Times; font-size: 14px">定义了内存操作（如共享变量的读写）的&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系。只有写入操作<strong><span style="color: #ff2600">&nbsp;</span></strong></span><span style="font-family: Times; font-size: 14px"><strong><span style="color: #ff2600">happen-before</span></strong></span><span style="font-family: Times; font-size: 14px"><strong><span style="color: #ff2600">&nbsp;</span></strong>读取操作时，才保证一个线程写入的结果对另一个线程的读取是可视的。</span><code style="font-size: 14px">synchronized</code><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><code style="font-size: 14px">volatile</code><span style="font-family: Times; font-size: 14px">&nbsp;构造&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系，</span><code style="font-size: 14px">Thread.start()</code><span style="font-family: Times; font-size: 14px">&nbsp;和</span><code style="font-size: 14px">Thread.join()</code><span style="font-family: Times; font-size: 14px">&nbsp;方法形成&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系。尤其是：</span> 
<ul style="font-family: Times; font-size: 14px"><li>线程中的每个操作&nbsp;<em>happen-before</em>&nbsp;稍后按程序顺序传入的该线程中的每个操作。</li><li>一个解除锁监视器的（<code>synchronized</code>&nbsp;阻塞或方法退出）<em>happen-before</em>&nbsp;相同监视器的每个后续锁（<code>synchronized</code>&nbsp;阻塞或方法进入）。并且因为&nbsp;<em>happen-before</em>&nbsp;关系是可传递的，所以解除锁定之前的线程的所有操作&nbsp;<em>happen-before</em>&nbsp;锁定该监视器的任何线程后续的所有操作。</li><li>写入&nbsp;<code>volatile</code>&nbsp;字段&nbsp;<em>happen-before</em>&nbsp;每个后续读取相同字段。<code>volatile</code>&nbsp;字段的读取和写入与进入和退出监视器具有相似的内存一致性效果，但<em>不</em>&nbsp;需要互斥锁。</li><li>在线程上调用&nbsp;<code>start</code>&nbsp;<em>happen-before</em>&nbsp;已启动的线程中的任何线程。</li><li>线程中的所有操作&nbsp;<em>happen-before</em>&nbsp;从该线程上的&nbsp;<code>join</code>&nbsp;成功返回的任何其他线程。</li></ul><code style="font-size: 14px">java.util.concurrent</code><span style="font-family: Times; font-size: 14px">&nbsp;中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是：</span> 
<ul style="font-family: Times; font-size: 14px"><li>线程中将一个对象放入任何并发 collection 之前的操作&nbsp;<em>happen-before</em>&nbsp;从另一线程中的 collection 访问或移除该元素的后续操作。</li><li>线程中向&nbsp;<code>Executor</code>&nbsp;提交&nbsp;<code>Runnable</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;其执行开始。同样适用于向&nbsp;<code>ExecutorService</code>&nbsp;提交&nbsp;<code>Callables</code>。</li><li>异步计算（由&nbsp;<code>Future</code>&nbsp;表示）所采取的操作&nbsp;<em>happen-before</em>&nbsp;通过另一线程中&nbsp;<code>Future.get()</code>&nbsp;获取结果后续的操作。</li><li>&#8220;释放&#8221;同步储存方法（如&nbsp;<code>Lock.unlock</code>、<code>Semaphore.release</code>&nbsp;和&nbsp;<code>CountDownLatch.countDown</code>）之前的操作&nbsp;<em>happen-before</em>&nbsp;另一线程中相同同步储存对象成功&#8220;获取&#8221;方法（如&nbsp;<code>Lock.lock</code>、<code>Semaphore.acquire</code>、<code>Condition.await</code>&nbsp;和&nbsp;<code>CountDownLatch.await</code>）的后续操作。</li><li>对于通过&nbsp;<code>Exchanger</code>&nbsp;成功交换对象的每个线程对，每个线程中&nbsp;<code>exchange()</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;另一线程中对应&nbsp;<code>exchange()</code>&nbsp;后续的操作。</li><li>调用&nbsp;<code>CyclicBarrier.await</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;屏障操作所执行的操作，屏障操作所执行的操作&nbsp;<em>happen-before</em>&nbsp;从另一线程中对应<code>await</code>&nbsp;成功返回的后续操作。</li></ul>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div>
<div style="font-size: 14px"><span style="font-family: Times">&nbsp;</span></div>
<h2 sizset="99" sizcache="3"><a name="t16"></a><span style="font-family: Times">Condition</span></h2>
<p style="font-family: Times; font-size: 14px" sizset="100" sizcache="3"><code>Condition</code>&nbsp;将&nbsp;<code>Object</code>&nbsp;监视器方法（<a href=""><code>wait</code></a>、<a href=""><code>notify</code></a>&nbsp;和&nbsp;<a href=""><code>notifyAll</code></a>）分解成截然不同的对象，以便通过将这些对象与任意&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;实现组合使用，为每个对象提供多个等待 set（wait-set）。其中，<code>Lock</code>&nbsp;替代了&nbsp;<code>synchronized</code>&nbsp;方法和语句的使用，<code>Condition</code>&nbsp;替代了 Object 监视器方法的使用。</p>
<p style="font-family: Times; font-size: 14px">条件（也称为<em>条件队列</em>&nbsp;或<em>条件变量</em>）为线程提供了一个含义，以便在某个状态条件现在可能为 true 的另一个线程通知它之前，一直挂起该线程（即让其&#8220;等待&#8221;）。因为访问此共享状态信息发生在不同的线程中，所以它必须受保护，因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是：<em>以原子方式</em>&nbsp;释放相关的锁，并挂起当前线程，就像&nbsp;<code>Object.wait</code>&nbsp;做的那样。</p>
<p style="font-family: Times; font-size: 14px" sizset="104" sizcache="3"><code>Condition</code>&nbsp;实例实质上被绑定到一个锁上。要为特定&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;实例获得&nbsp;<code>Condition</code>&nbsp;实例，请使用其&nbsp;<a href=""><code>newCondition()</code></a>&nbsp;方法。</p>
<p style="font-family: Times; font-size: 14px" sizset="106" sizcache="3">作为一个示例，假定有一个绑定的缓冲区，它支持&nbsp;<code>put</code>&nbsp;和&nbsp;<code>take</code>&nbsp;方法。如果试图在空的缓冲区上执行&nbsp;<code>take</code>&nbsp;操作，则在某一个项变得可用之前，线程将一直阻塞；如果试图在满的缓冲区上执行&nbsp;<code>put</code>&nbsp;操作，则在有空间变得可用之前，线程将一直阻塞。我们喜欢在单独的等待 set 中保存&nbsp;<code>put</code>&nbsp;线程和&nbsp;<code>take</code>&nbsp;线程，这样就可以在缓冲区中的项或空间变得可用时利用最佳规划，一次只通知一个线程。可以使用两个&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Condition</code></a>&nbsp;实例来做到这一点。</p><pre style="font-size: 14px"> class BoundedBuffer {
   <strong>final Lock lock = new ReentrantLock();</strong>
   final Condition notFull  = <strong>lock.newCondition(); </strong>
   final Condition notEmpty = <strong>lock.newCondition(); </strong>

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     <strong>lock.lock();
     try {</strong>
       while (count == items.length) 
         <strong>notFull.await();</strong>
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       <strong>notEmpty.signal();
     } finally {
       lock.unlock();
     }</strong>
   }

   public Object take() throws InterruptedException {
     <strong>lock.lock();
     try {</strong>
       while (count == 0) 
         <strong>notEmpty.await();</strong>
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       <strong>notFull.signal();</strong>
       return x;
     <strong>} finally {
       lock.unlock();
     }</strong>
   } 
 }
 

</pre><span style="font-family: Times; font-size: 14px">（</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ArrayBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供了这项功能，因此没有理由去实现这个示例类。）</span> 
<p style="font-family: Times; font-size: 14px"><code>Condition</code>&nbsp;实现可以提供不同于&nbsp;<code>Object</code>&nbsp;监视器方法的行为和语义，比如受保证的通知排序，或者在执行通知时不需要保持一个锁。如果某个实现提供了这样特殊的语义，则该实现必须记录这些语义。</p>
<p style="font-family: Times; font-size: 14px" sizset="108" sizcache="3">注意，<code>Condition</code>&nbsp;实例只是一些普通的对象，它们自身可以用作&nbsp;<code>synchronized</code>&nbsp;语句中的目标，并且可以调用自己的&nbsp;<a href=""><code>wait</code></a>&nbsp;和<a href=""><code>notification</code></a>&nbsp;监视器方法。获取&nbsp;<code>Condition</code>&nbsp;实例的监视器锁或者使用其监视器方法，与获取和该&nbsp;<code>Condition</code>&nbsp;相关的&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;或使用其&nbsp;<a href=""><code>waiting</code></a>&nbsp;和&nbsp;<a href=""><code>signalling</code></a>&nbsp;方法没有什么特定的关系。为了避免混淆，建议除了在其自身的实现中之外，切勿以这种方式使用<code>Condition</code>&nbsp;实例。</p>
<p style="font-family: Times; font-size: 14px" sizset="113" sizcache="3">除非另行说明，否则为任何参数传递&nbsp;<code>null</code>&nbsp;值将导致抛出&nbsp;<a title="java.lang 中的类" href=""><code>NullPointerException</code></a>。</p>
<h3 style="font-family: Times" sizset="114" sizcache="3"><a name="t17"></a>实现注意事项</h3>
<p style="font-family: Times; font-size: 14px">在等待&nbsp;<code>Condition</code>&nbsp;时，允许发生&#8220;<em>虚假唤醒</em>&#8221;，这通常作为对基础平台语义的让步。对于大多数应用程序，这带来的实际影响很小，因为&nbsp;<code>Condition</code>&nbsp;应该总是在一个循环中被等待，并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒，但建议应用程序程序员总是假定这些虚假唤醒可能发生，因此总是在一个循环中等待。</p>
<p style="font-family: Times; font-size: 14px">三种形式的条件等待（可中断、不可中断和超时）在一些平台上的实现以及它们的性能特征可能会有所不同。尤其是它可能很难提供这些特性和维护特定语义，比如排序保证。更进一步地说，中断线程实际挂起的能力在所有平台上并不是总是可行的。</p>
<p style="font-family: Times; font-size: 14px">因此，并不要求某个实现为所有三种形式的等待定义完全相同的保证或语义，也不要求其支持中断线程的实际挂起。</p>
<p style="font-family: Times; font-size: 14px">要求实现清楚地记录每个等待方法提供的语义和保证，在某个实现不支持中断线程的挂起时，它必须遵从此接口中定义的中断语义。</p>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times">由于中断通常意味着取消，而又通常很少进行中断检查，因此实现可以先于普通方法的返回来对中断进行响应。即使出现在另一个操作后的中断可能会释放线程锁时也是如此。实现应记录此行为。</span></div>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div><img src ="http://www.blogjava.net/stevenjohn/aggbug/398876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-05-06 18:33 <a href="http://www.blogjava.net/stevenjohn/archive/2013/05/06/398876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 高并发 基础知识 </title><link>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396809.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 21 Mar 2013 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396809.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/396809.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/396809.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/396809.html</trackback:ping><description><![CDATA[<div style="border-bottom: #ccc 1px solid; min-width: 200px; border-left: #ccc 1px solid; padding-bottom: 4px; padding-left: 10px; padding-right: 10px;background: #eee; float: left; border-top: #ccc 1px solid; border-right: #ccc 1px solid; padding-top: 4px" sizset="27" sizcache="3">
<p style="text-align: right; margin: 0px" sizset="27" sizcache="3"><span style="float: left" sizset="27" sizcache="3">目录<a title="系统根据文章中H1到H6标签自动生成文章目录" href="http://blog.csdn.net/fh13760184/article/details/8551546#">(?)</a></span><a title="收起" href="http://blog.csdn.net/fh13760184/article/details/8551546#">[-]</a></p>
<ol style="line-height: 160%; padding-left: 14px; margin-left: 14px" sizset="29" sizcache="3" jquery1363852899000="22"><li sizset="29" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t0"></a></li><li sizset="30" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t1">锁</a></li><li sizset="31" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t2">volatile 使用条件必须同时满足所有条件</a></li><li sizset="32" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t3"></a></li><li sizset="33" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t4"></a></li><li sizset="34" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t5">高并发术语</a></li><li sizset="35" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t6"></a></li><li sizset="36" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t7">synchronized</a></li><li sizset="37" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t8">volatile</a></li><li sizset="38" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t9">concurrent</a></li><li sizset="39" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t10">执行程序</a></li><li sizset="40" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t11">队列</a></li><li sizset="41" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t12">计时</a></li><li sizset="42" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t13">同步器</a></li><li sizset="43" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t14">并发 Collection</a></li><li sizset="44" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t15">内存一致性属性</a></li><li sizset="45" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t16">Condition</a></li>
<ol sizset="46" sizcache="3"><li sizset="46" sizcache="3"><a href="http://blog.csdn.net/fh13760184/article/details/8551546#t17">实现注意事项</a></li></ol></ol></div>
<div style="clear: both"></div>
<div id="article_content" class="article_content" sizset="47" sizcache="3">
<h2 style="font-family: Times" sizset="47" sizcache="3"><a name="t0"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="48" sizcache="3"><a name="t1"></a>锁:</h2>
<div>
<ol><li>内置锁 (监视器锁): 每个java对象都可以做一个实现同步的锁,这些锁被成为内置锁. 获得锁的唯一途径就是进入有这个锁保护的代码块或方法</li><li>重入锁: 由于内置锁是可重入的,因此如果某个线程试图获得一个以已经由他自己持有的锁, 那么这个请求就会成功.重入意味着获取锁的操作粒度是"线程",而不是"调用"</li></ol><span style="white-space: pre"></span></div>
<div><span style="white-space: pre"></span></div>
<h2 style="font-family: Times" sizset="49" sizcache="3"><a name="t2"></a>volatile 使用条件(<span style="color: rgb(255,102,102)">必须同时满足所有条件</span>):</h2>
<div>
<ol><li>对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值</li><li>该变量不会与其他状态变量一起纳入不变性条件中</li><li>在访问变量时间不需要加锁</li></ol></div>
<h2 style="font-family: Times" sizset="50" sizcache="3"><a name="t3"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="51" sizcache="3"><a name="t4"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="52" sizcache="3"><a name="t5"></a>高并发术语</h2>
<address><span style="font-weight: normal"><br /></span></address>
<address><span style="font-weight: normal"><br /></span></address>
<address><span style="font-weight: normal"></span>
<table style="line-height: 19px; font-family: Lucida,'Lucida Grande',Tahoma,sans-serif; color: rgb(0,0,0)" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">术语</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">英文单词</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">描述</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial"><strong>比较并交换</strong></span></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">Compare and Swap</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CAS操作需要输入两个数值，一个旧值（期望操作前的值）和一个新值，在操作期间先比较下旧值有没有发生变化，如果没有发生变化，才交换成新值，发生了变化则不交换</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong><span style="text-align: center; font-family: Arial">CPU流水线</span></strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CPU pipeline</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">CPU流水线的工作方式就象工业生产上的装配流水线，在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线，然后将一条X86指令分成5~6步后再由这些电路单元分别执行，这样就能实现在一个CPU时钟周期完成一条指令，因此提高CPU的运算速度</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial"><strong>内存顺序冲突</strong></span></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">Memory order violation</span></span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px"><span style="text-align: center; font-family: Arial">内存顺序冲突一般是由假共享引起，假共享是指多个CPU同时修改同一个缓存行的不同部分而引起其中一个CPU的操作无效，当出现这个内存顺序冲突时，CPU必须清空流水线</span>。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>共享变量</strong></span></p></td>
<td valign="top" width="155"><span style="font-size: 12px"><br /></span></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">在多个线程之间能够被共享的变量被称为共享变量。共享变量包括所有的实例变量，静态变量和数组元素。他们都被存放在堆内存中，Volatile只作用于共享变量。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>内存屏障</strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Memory Barriers</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">是一组处理器指令，用于实现对内存操作的顺序限制。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px"><strong>缓冲行</strong></span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Cache line</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">缓存中可以分配的最小存储单位。处理器填写缓存线时会加载整个缓存线，需要使用多个主内存读周期。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">原子操作</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">Atomic operations</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">不可中断的一个或一系列操作。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">缓存行填充</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">cache line fill</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">当处理器识别到从内存中读取操作数是可缓存的，处理器读取整个缓存行到适当的缓存（L1，L2，L3的或所有）</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">缓存命中</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">cache hit</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">如果进行高速缓存行填充操作的内存位置仍然是下次处理器访问的地址时，处理器从缓存中读取操作数，而不是从内存。</span></p></td></tr>
<tr>
<td valign="top" width="110">
<p><span style="font-size: 12px">写命中</span></p></td>
<td valign="top" width="155">
<p><span style="font-size: 12px">write hit</span></p></td>
<td valign="top" width="288">
<p><span style="font-size: 12px">当处理器将操作数写回到一个内存缓存的区域时，它首先会检查这个缓存的内存地址是否在缓存行中，如果存在一个有效的缓存行，则处理器将这个操作数写回到缓存，而不是写回到内存，这个操作被称为写命中。</span></p></td></tr></tbody></table><br /></address>
<h2 style="font-family: Times" sizset="53" sizcache="3"><a name="t6"></a><br />&nbsp;</h2>
<h2 style="font-family: Times" sizset="54" sizcache="3"><a name="t7"></a>synchronized</h2>
<h2 style="font-family: Times" sizset="55" sizcache="3"><a name="t8"></a>volatile<br /></h2>
<h2 style="font-family: Times" sizset="56" sizcache="3"><a name="t9"></a>concurrent&nbsp;</h2>
<p style="font-family: Times; font-size: 14px"></p>
<p style="font-family: Times; font-size: 14px">在并发编程中很常用的实用工具类。此包包括了几个小的、已标准化的可扩展框架，以及一些提供有用功能的类，没有这些类，这些功能会很难实现或实现起来冗长乏味。下面简要描述主要的组件。另请参阅&nbsp;<tt>locks</tt>&nbsp;和&nbsp;<tt>atomic</tt>&nbsp;包。</p>
<h2 style="font-family: Times" sizset="57" sizcache="3"><a name="t10"></a>执行程序</h2><span style="font-family: Times; font-size: 14px">接口。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Executor</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个简单的标准化接口，用于定义类似于线程的自定义子系统，包括线程池、异步 IO 和轻量级任务框架。根据所使用的具体 Executor 类的不同，可能在新创建的线程中，现有的任务执行线程中，或者调用&nbsp;</span><tt style="font-size: 14px">execute()</tt><span style="font-family: Times; font-size: 14px">&nbsp;的线程中执行任务，并且可能顺序或并发执行。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>ExecutorService</code></a><span style="font-family: Times; font-size: 14px">&nbsp;提供了多个完整的异步任务执行框架。ExecutorService 管理任务的排队和安排，并允许受控制的关闭。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>ScheduledExecutorService</code></a><span style="font-family: Times; font-size: 14px">&nbsp;子接口及相关的接口添加了对延迟的和定期任务执行的支持。ExecutorService 提供了安排异步执行的方法，可执行由&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Callable</code></a><span style="font-family: Times; font-size: 14px">&nbsp;表示的任何函数，结果类似于&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.lang 中的接口" href=""><code>Runnable</code></a><span style="font-family: Times; font-size: 14px">。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>Future</code></a><span style="font-family: Times; font-size: 14px">&nbsp;返回函数的结果，允许确定执行是否完成，并提供取消执行的方法。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>RunnableFuture</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是拥有&nbsp;</span><tt style="font-size: 14px">run</tt><span style="font-family: Times; font-size: 14px">&nbsp;方法的 Future，</span><tt style="font-size: 14px">run</tt><span style="font-family: Times; font-size: 14px">&nbsp;方法执行时将设置其结果。</span> 
<p style="font-family: Times; font-size: 14px" sizset="65" sizcache="3"><strong>实现。</strong>类&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ThreadPoolExecutor</code></a>&nbsp;和&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ScheduledThreadPoolExecutor</code></a>&nbsp;提供可调的、灵活的线程池。<a title="java.util.concurrent 中的类" href=""><code>Executors</code></a>&nbsp;类提供大多数 Executor 的常见类型和配置的工厂方法，以及使用它们的几种实用工具方法。其他基于 Executor 的实用工具包括具体类&nbsp;<a title="java.util.concurrent 中的类" href=""><code>FutureTask</code></a>，它提供 Future 的常见可扩展实现，以及&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ExecutorCompletionService</code></a>，它有助于协调对异步任务组的处理。</p>
<h2 style="font-family: Times" sizset="70" sizcache="3"><a name="t11"></a>队列</h2><span style="font-family: Times; font-size: 14px">java.util.concurrent&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentLinkedQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>BlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;接口，该接口定义了 put 和 take 的阻塞版本：</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>LinkedBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ArrayBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>SynchronousQueue</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>PriorityBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>DelayQueue</code></a><span style="font-family: Times; font-size: 14px">。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的接口" href=""><code>BlockingDeque</code></a><span style="font-family: Times; font-size: 14px">&nbsp;接口扩展&nbsp;</span><tt style="font-size: 14px">BlockingQueue</tt><span style="font-family: Times; font-size: 14px">，以支持 FIFO 和 LIFO（基于堆栈）操作。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>LinkedBlockingDeque</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供一个实现。</span> 
<h2 style="font-family: Times" sizset="80" sizcache="3"><a name="t12"></a>计时</h2><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的枚举" href=""><code>TimeUnit</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类为指定和控制基于超时的操作提供了多重粒度（包括纳秒级）。该包中的大多数类除了包含不确定的等待之外，还包含基于超时的操作。在使用超时的所有情况中，超时指定了在表明已超时前该方法应该等待的最少时间。在超时发生后，实现会&#8220;尽力&#8221;检测超时。但是，在检测超时与超时之后再次实际执行线程之间可能要经过不确定的时间。接受超时期参数的所有方法将小于等于 0 的值视为根本不会等待。要&#8220;永远&#8221;等待，可以使用&nbsp;</span><tt style="font-size: 14px">Long.MAX_VALUE</tt><span style="font-family: Times; font-size: 14px">&nbsp;值。</span> 
<h2 style="font-family: Times" sizset="82" sizcache="3"><a name="t13"></a>同步器</h2><span style="font-family: Times; font-size: 14px">四个类可协助实现常见的专用同步语句。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>Semaphore</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个经典的并发工具。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CountDownLatch</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个极其简单但又极其常用的实用工具，用于在保持给定数目的信号、事件或条件前阻塞执行。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CyclicBarrier</code></a><span style="font-family: Times; font-size: 14px">&nbsp;是一个可重置的多路同步点，在某些并行编程风格中很有用。</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>Exchanger</code></a><span style="font-family: Times; font-size: 14px">&nbsp;允许两个线程在 collection 点交换对象，它在多流水线设计中是有用的。</span> 
<h2 style="font-family: Times" sizset="87" sizcache="3"><a name="t14"></a>并发 Collection</h2><span style="font-family: Times; font-size: 14px">除队列外，此包还提供了设计用于多线程上下文中的 Collection 实现：</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentHashMap</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentSkipListMap</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ConcurrentSkipListSet</code></a><span style="font-family: Times; font-size: 14px">、</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CopyOnWriteArrayList</code></a><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>CopyOnWriteArraySet</code></a><span style="font-family: Times; font-size: 14px">。当期望许多线程访问一个给定 collection 时，</span><tt style="font-size: 14px">ConcurrentHashMap</tt><span style="font-family: Times; font-size: 14px">&nbsp;通常优于同步的&nbsp;</span><tt style="font-size: 14px">HashMap</tt><span style="font-family: Times; font-size: 14px">，</span><tt style="font-size: 14px">ConcurrentSkipListMap</tt><span style="font-family: Times; font-size: 14px">&nbsp;通常优于同步的&nbsp;</span><tt style="font-size: 14px">TreeMap</tt><span style="font-family: Times; font-size: 14px">。当期望的读数和遍历远远大于列表的更新数时，</span><tt style="font-size: 14px">CopyOnWriteArrayList</tt><span style="font-family: Times; font-size: 14px">&nbsp;优于同步的&nbsp;</span><tt style="font-size: 14px">ArrayList</tt><span style="font-family: Times; font-size: 14px">。</span> 
<p style="font-family: Times; font-size: 14px" sizset="93" sizcache="3">此包中与某些类一起使用的&#8220;Concurrent&amp;rdquo前缀;是一种简写，表明与类似的&#8220;同步&#8221;类有所不同。例如，<tt>java.util.Hashtable</tt>&nbsp;和<tt>Collections.synchronizedMap(new HashMap())</tt>&nbsp;是同步的，但&nbsp;<a title="java.util.concurrent 中的类" href=""><code>ConcurrentHashMap</code></a>&nbsp;则是&#8220;并发的&#8221;。并发 collection 是线程安全的，但是不受单个排他锁的管理。在 ConcurrentHashMap 这一特定情况下，它可以安全地允许进行任意数目的并发读取，以及数目可调的并发写入。需要通过单个锁不允许对 collection 的所有访问时，&#8220;同步&#8221;类是很有用的，其代价是较差的可伸缩性。在期望多个线程访问公共 collection 的其他情况中，通常&#8220;并发&#8221;版本要更好一些。当 collection 是未共享的，或者仅保持其他锁时 collection 是可访问的情况下，非同步 collection 则要更好一些。</p>
<p style="font-family: Times; font-size: 14px" sizset="94" sizcache="3">大多数并发 Collection 实现（包括大多数 Queue）与常规的 java.util 约定也不同，因为它们的迭代器提供了<em>弱一致的</em>，而不是快速失败的遍历。弱一致的迭代器是线程安全的，但是在迭代时没有必要冻结 collection，所以它不一定反映自迭代器创建以来的所有更新。<a id="MemoryVisibility" name="MemoryVisibility"></a></p>
<h2 style="font-family: Times" sizset="95" sizcache="3"><a name="t15"></a><a id="MemoryVisibility" name="MemoryVisibility">内存一致性属性</a></h2><a style="font-family: Times; font-size: 14px" id="MemoryVisibility" name="MemoryVisibility"></a><a style="font-family: Times; font-size: 14px" href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">Java Language Specification 第 17 章</a><span style="font-family: Times; font-size: 14px">定义了内存操作（如共享变量的读写）的&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系。只有写入操作<strong><span style="color: #ff2600">&nbsp;</span></strong></span><span style="font-family: Times; font-size: 14px"><strong><span style="color: #ff2600">happen-before</span></strong></span><span style="font-family: Times; font-size: 14px"><strong><span style="color: #ff2600">&nbsp;</span></strong>读取操作时，才保证一个线程写入的结果对另一个线程的读取是可视的。</span><code style="font-size: 14px">synchronized</code><span style="font-family: Times; font-size: 14px">&nbsp;和&nbsp;</span><code style="font-size: 14px">volatile</code><span style="font-family: Times; font-size: 14px">&nbsp;构造&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系，</span><code style="font-size: 14px">Thread.start()</code><span style="font-family: Times; font-size: 14px">&nbsp;和</span><code style="font-size: 14px">Thread.join()</code><span style="font-family: Times; font-size: 14px">&nbsp;方法形成&nbsp;</span><span style="font-family: Times; font-size: 14px">happen-before</span><span style="font-family: Times; font-size: 14px">&nbsp;关系。尤其是：</span> 
<ul style="font-family: Times; font-size: 14px"><li>线程中的每个操作&nbsp;<em>happen-before</em>&nbsp;稍后按程序顺序传入的该线程中的每个操作。</li><li>一个解除锁监视器的（<code>synchronized</code>&nbsp;阻塞或方法退出）<em>happen-before</em>&nbsp;相同监视器的每个后续锁（<code>synchronized</code>&nbsp;阻塞或方法进入）。并且因为&nbsp;<em>happen-before</em>&nbsp;关系是可传递的，所以解除锁定之前的线程的所有操作&nbsp;<em>happen-before</em>&nbsp;锁定该监视器的任何线程后续的所有操作。</li><li>写入&nbsp;<code>volatile</code>&nbsp;字段&nbsp;<em>happen-before</em>&nbsp;每个后续读取相同字段。<code>volatile</code>&nbsp;字段的读取和写入与进入和退出监视器具有相似的内存一致性效果，但<em>不</em>&nbsp;需要互斥锁。</li><li>在线程上调用&nbsp;<code>start</code>&nbsp;<em>happen-before</em>&nbsp;已启动的线程中的任何线程。</li><li>线程中的所有操作&nbsp;<em>happen-before</em>&nbsp;从该线程上的&nbsp;<code>join</code>&nbsp;成功返回的任何其他线程。</li></ul><code style="font-size: 14px">java.util.concurrent</code><span style="font-family: Times; font-size: 14px">&nbsp;中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是：</span> 
<ul style="font-family: Times; font-size: 14px"><li>线程中将一个对象放入任何并发 collection 之前的操作&nbsp;<em>happen-before</em>&nbsp;从另一线程中的 collection 访问或移除该元素的后续操作。</li><li>线程中向&nbsp;<code>Executor</code>&nbsp;提交&nbsp;<code>Runnable</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;其执行开始。同样适用于向&nbsp;<code>ExecutorService</code>&nbsp;提交&nbsp;<code>Callables</code>。</li><li>异步计算（由&nbsp;<code>Future</code>&nbsp;表示）所采取的操作&nbsp;<em>happen-before</em>&nbsp;通过另一线程中&nbsp;<code>Future.get()</code>&nbsp;获取结果后续的操作。</li><li>&#8220;释放&#8221;同步储存方法（如&nbsp;<code>Lock.unlock</code>、<code>Semaphore.release</code>&nbsp;和&nbsp;<code>CountDownLatch.countDown</code>）之前的操作&nbsp;<em>happen-before</em>&nbsp;另一线程中相同同步储存对象成功&#8220;获取&#8221;方法（如&nbsp;<code>Lock.lock</code>、<code>Semaphore.acquire</code>、<code>Condition.await</code>&nbsp;和&nbsp;<code>CountDownLatch.await</code>）的后续操作。</li><li>对于通过&nbsp;<code>Exchanger</code>&nbsp;成功交换对象的每个线程对，每个线程中&nbsp;<code>exchange()</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;另一线程中对应&nbsp;<code>exchange()</code>&nbsp;后续的操作。</li><li>调用&nbsp;<code>CyclicBarrier.await</code>&nbsp;之前的操作&nbsp;<em>happen-before</em>&nbsp;屏障操作所执行的操作，屏障操作所执行的操作&nbsp;<em>happen-before</em>&nbsp;从另一线程中对应<code>await</code>&nbsp;成功返回的后续操作。</li></ul>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div>
<div style="font-size: 14px"><span style="font-family: Times">&nbsp;</span></div>
<h2 sizset="99" sizcache="3"><a name="t16"></a><span style="font-family: Times">Condition</span></h2>
<p style="font-family: Times; font-size: 14px" sizset="100" sizcache="3"><code>Condition</code>&nbsp;将&nbsp;<code>Object</code>&nbsp;监视器方法（<a href=""><code>wait</code></a>、<a href=""><code>notify</code></a>&nbsp;和&nbsp;<a href=""><code>notifyAll</code></a>）分解成截然不同的对象，以便通过将这些对象与任意&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;实现组合使用，为每个对象提供多个等待 set（wait-set）。其中，<code>Lock</code>&nbsp;替代了&nbsp;<code>synchronized</code>&nbsp;方法和语句的使用，<code>Condition</code>&nbsp;替代了 Object 监视器方法的使用。</p>
<p style="font-family: Times; font-size: 14px">条件（也称为<em>条件队列</em>&nbsp;或<em>条件变量</em>）为线程提供了一个含义，以便在某个状态条件现在可能为 true 的另一个线程通知它之前，一直挂起该线程（即让其&#8220;等待&#8221;）。因为访问此共享状态信息发生在不同的线程中，所以它必须受保护，因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是：<em>以原子方式</em>&nbsp;释放相关的锁，并挂起当前线程，就像&nbsp;<code>Object.wait</code>&nbsp;做的那样。</p>
<p style="font-family: Times; font-size: 14px" sizset="104" sizcache="3"><code>Condition</code>&nbsp;实例实质上被绑定到一个锁上。要为特定&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;实例获得&nbsp;<code>Condition</code>&nbsp;实例，请使用其&nbsp;<a href=""><code>newCondition()</code></a>&nbsp;方法。</p>
<p style="font-family: Times; font-size: 14px" sizset="106" sizcache="3">作为一个示例，假定有一个绑定的缓冲区，它支持&nbsp;<code>put</code>&nbsp;和&nbsp;<code>take</code>&nbsp;方法。如果试图在空的缓冲区上执行&nbsp;<code>take</code>&nbsp;操作，则在某一个项变得可用之前，线程将一直阻塞；如果试图在满的缓冲区上执行&nbsp;<code>put</code>&nbsp;操作，则在有空间变得可用之前，线程将一直阻塞。我们喜欢在单独的等待 set 中保存&nbsp;<code>put</code>&nbsp;线程和&nbsp;<code>take</code>&nbsp;线程，这样就可以在缓冲区中的项或空间变得可用时利用最佳规划，一次只通知一个线程。可以使用两个&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Condition</code></a>&nbsp;实例来做到这一点。</p><pre style="font-size: 14px"> class BoundedBuffer {
   <strong>final Lock lock = new ReentrantLock();</strong>
   final Condition notFull  = <strong>lock.newCondition(); </strong>
   final Condition notEmpty = <strong>lock.newCondition(); </strong>

   final Object[] items = new Object[100];
   int putptr, takeptr, count;

   public void put(Object x) throws InterruptedException {
     <strong>lock.lock();
     try {</strong>
       while (count == items.length) 
         <strong>notFull.await();</strong>
       items[putptr] = x; 
       if (++putptr == items.length) putptr = 0;
       ++count;
       <strong>notEmpty.signal();
     } finally {
       lock.unlock();
     }</strong>
   }

   public Object take() throws InterruptedException {
     <strong>lock.lock();
     try {</strong>
       while (count == 0) 
         <strong>notEmpty.await();</strong>
       Object x = items[takeptr]; 
       if (++takeptr == items.length) takeptr = 0;
       --count;
       <strong>notFull.signal();</strong>
       return x;
     <strong>} finally {
       lock.unlock();
     }</strong>
   } 
 }
 

</pre><span style="font-family: Times; font-size: 14px">（</span><a style="font-family: Times; font-size: 14px" title="java.util.concurrent 中的类" href=""><code>ArrayBlockingQueue</code></a><span style="font-family: Times; font-size: 14px">&nbsp;类提供了这项功能，因此没有理由去实现这个示例类。）</span> 
<p style="font-family: Times; font-size: 14px"><code>Condition</code>&nbsp;实现可以提供不同于&nbsp;<code>Object</code>&nbsp;监视器方法的行为和语义，比如受保证的通知排序，或者在执行通知时不需要保持一个锁。如果某个实现提供了这样特殊的语义，则该实现必须记录这些语义。</p>
<p style="font-family: Times; font-size: 14px" sizset="108" sizcache="3">注意，<code>Condition</code>&nbsp;实例只是一些普通的对象，它们自身可以用作&nbsp;<code>synchronized</code>&nbsp;语句中的目标，并且可以调用自己的&nbsp;<a href=""><code>wait</code></a>&nbsp;和<a href=""><code>notification</code></a>&nbsp;监视器方法。获取&nbsp;<code>Condition</code>&nbsp;实例的监视器锁或者使用其监视器方法，与获取和该&nbsp;<code>Condition</code>&nbsp;相关的&nbsp;<a title="java.util.concurrent.locks 中的接口" href=""><code>Lock</code></a>&nbsp;或使用其&nbsp;<a href=""><code>waiting</code></a>&nbsp;和&nbsp;<a href=""><code>signalling</code></a>&nbsp;方法没有什么特定的关系。为了避免混淆，建议除了在其自身的实现中之外，切勿以这种方式使用<code>Condition</code>&nbsp;实例。</p>
<p style="font-family: Times; font-size: 14px" sizset="113" sizcache="3">除非另行说明，否则为任何参数传递&nbsp;<code>null</code>&nbsp;值将导致抛出&nbsp;<a title="java.lang 中的类" href=""><code>NullPointerException</code></a>。</p>
<h3 style="font-family: Times" sizset="114" sizcache="3"><a name="t17"></a>实现注意事项</h3>
<p style="font-family: Times; font-size: 14px">在等待&nbsp;<code>Condition</code>&nbsp;时，允许发生&#8220;<em>虚假唤醒</em>&#8221;，这通常作为对基础平台语义的让步。对于大多数应用程序，这带来的实际影响很小，因为&nbsp;<code>Condition</code>&nbsp;应该总是在一个循环中被等待，并测试正被等待的状态声明。某个实现可以随意移除可能的虚假唤醒，但建议应用程序程序员总是假定这些虚假唤醒可能发生，因此总是在一个循环中等待。</p>
<p style="font-family: Times; font-size: 14px">三种形式的条件等待（可中断、不可中断和超时）在一些平台上的实现以及它们的性能特征可能会有所不同。尤其是它可能很难提供这些特性和维护特定语义，比如排序保证。更进一步地说，中断线程实际挂起的能力在所有平台上并不是总是可行的。</p>
<p style="font-family: Times; font-size: 14px">因此，并不要求某个实现为所有三种形式的等待定义完全相同的保证或语义，也不要求其支持中断线程的实际挂起。</p>
<p style="font-family: Times; font-size: 14px">要求实现清楚地记录每个等待方法提供的语义和保证，在某个实现不支持中断线程的挂起时，它必须遵从此接口中定义的中断语义。</p>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times">由于中断通常意味着取消，而又通常很少进行中断检查，因此实现可以先于普通方法的返回来对中断进行响应。即使出现在另一个操作后的中断可能会释放线程锁时也是如此。实现应记录此行为。</span></div>
<div style="font-family: Arial; font-size: 14px"><span style="font-family: Times"><br /></span></div></div><br /><br /><br /><br /><a href="http://blog.csdn.net/fh13760184/article/details/8551546">http://blog.csdn.net/fh13760184/article/details/8551546</a>#<img src ="http://www.blogjava.net/stevenjohn/aggbug/396809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-03-21 16:03 <a href="http://www.blogjava.net/stevenjohn/archive/2013/03/21/396809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java处理高并发高负载类网站的优化方法</title><link>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396808.html</link><dc:creator>abin</dc:creator><author>abin</author><pubDate>Thu, 21 Mar 2013 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396808.html</guid><wfw:comment>http://www.blogjava.net/stevenjohn/comments/396808.html</wfw:comment><comments>http://www.blogjava.net/stevenjohn/archive/2013/03/21/396808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/stevenjohn/comments/commentRss/396808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/stevenjohn/services/trackbacks/396808.html</trackback:ping><description><![CDATA[<p>java处理高并发高负载类网站中数据库的设计方法（java教程,java处理大量数据，java高负载数据）</p>
<p><strong><span style="color: #e53333">一：高并发高负载类网站关注点之数据库 </span></strong></p>
<p>没错,首先是数据库,这是大多数应用所面临的首个SPOF。尤其是Web2.0的应用，数据库的响应是首先要解决的。<br />一般来说MySQL是最常用的，可能最初是一个mysql主机，当数据增加到100万以上，那么，MySQL的效能急剧下降。常用的优化措施是M-S（主-从）方式进行同步复制，将查询和操作和分别在不同的服务器上进行操作。我推荐的是M-M-Slaves方式，2个主Mysql，多个Slaves，需要注意的是，虽然有2个Master，但是同时只有1个是Active，我们可以在一定时候切换。之所以用2个M，是保证M不会又成为系统的SPOF。<br />Slaves可以进一步负载均衡，可以结合LVS,从而将select操作适当的平衡到不同的slaves上。<br />以上架构可以抗衡到一定量的负载，但是随着用户进一步增加，你的用户表数据超过1千万，这时那个M变成了SPOF。你不能任意扩充Slaves，否则复制同步的开销将直线上升，怎么办？我的方法是表分区，从业务层面上进行分区。最简单的，以用户数据为例。根据一定的切分方式，比如id，切分到不同的数据库集群去。 </p>
<p>全局数据库用于meta数据的查询。缺点是每次查询，会增加一次，比如你要查一个用户nightsailer,你首先要到全局数据库群找到nightsailer对应的cluster id，然后再到指定的cluster找到nightsailer的实际数据。<br />每个cluster可以用m-m方式，或者m-m-slaves方式。这是一个可以扩展的结构，随着负载的增加，你可以简单的增加新的mysql cluster进去。</p>
<p>需要注意的是：<br />1、禁用全部auto_increment的字段<br />2、id需要采用通用的算法集中分配<br />3、要具有比较好的方法来监控mysql主机的负载和服务的运行状态。如果你有30台以上的mysql数据库在跑就明白我的意思了。<br />4、不要使用持久性链接（不要用pconnect）,相反，使用sqlrelay这种第三方的数据库链接池，或者干脆自己做，因为php4中mysql的链接池经常出问题。<br /><strong>&nbsp;<br /><span style="color: #e53333">二：高并发高负载网站的系统架构之HTML静态化 </span></strong></p>
<p>其实大家都知道，效率最高、消耗最小的就是纯<a href="http://www.ablanxue.com/shtml/201207/776.shtml" target="_blank">静态化</a>&nbsp;<a href="http://www.ablanxue.com/shtml/201207/776.shtml">http://www.ablanxue.com/shtml/201207/776.shtml</a>的html页面，所以我们尽可能使我们的网站上的页面采用静态页面来实现，这个最简单的方法其实也是 最有效的方法。但是对于大量内容并且频繁更新的网站，我们无法全部手动去挨个实现，于是出现了我们常见的信息发布系统CMS，像我们常访问的各个门户站点 的新闻频道，甚至他们的其他频道，都是通过信息发布系统来管理和实现的，信息发布系统可以实现最简单的信息录入自动生成静态页面，还能具备频道管理、权限 管理、自动抓取等功能，对于一个大型网站来说，拥有一套高效、可管理的CMS是必不可少的。<br />　　<br />　　除了门户和信息发布类型的网站，对于交互性要求很高的社区类型网站来说，尽可能的静态化也是提高性能的必要手段，将社区内的帖子、文章进行实时的静态化，有更新的时候再重新静态化也是大量使用的策略，像Mop的大杂烩就是使用了这样的策略，网易社区等也是如此。<br />　　<br />　 　同时，html静态化也是某些缓存策略使用的手段，对于系统中频繁使用数据库查询但是内容更新很小的应用，可以考虑使用html静态化来实现，比如论坛 中论坛的公用设置信息，这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中，这些信息其实大量被前台程序调用，但是更新频率很小，可以考虑将这 部分内容进行后台更新的时候进行静态化，这样避免了大量的数据库访问请求高并发。<br />　　 </p>
<p>网站HTML静态化解决方案 <br />当一个Servlet资源请求到达WEB服务器之后我们会填充指定的JSP页面来响应请求:</p>
<p>HTTP请求---Web服务器---Servlet--业务逻辑处理--访问数据--填充JSP--响应请求</p>
<p>HTML静态化之后:</p>
<p>HTTP请求---Web服务器---Servlet--HTML--响应请求</p>
<p>静态访求如下</p>
<p>Servlet:</p>
<p>public void doGet(HttpServletRequest request, HttpServletResponse response)&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws ServletException, IOException {&nbsp; <br />&nbsp;&nbsp;&nbsp; if(request.getParameter("chapterId") != null){&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String chapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String chapterFilePath = getServletContext().getRealPath("/") + chapterFileName;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File chapterFile = new File(chapterFilePath);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有这个文件就告诉浏览器转向&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));//章节信息&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setAttribute("novelChapter", novelChapter);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setAttribute("lastPageId", lastPageId);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.setAttribute("nextPageId", nextPageId);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(),&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chapterFileName, chapterFilePath, "/bookRead.jsp");&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; <br />}&nbsp; <br />生成HTML静态页面的类:</p>
<p>package com.jb.y2t034.thefifth.web.servlet;&nbsp; <br />import java.io.ByteArrayOutputStream;&nbsp; <br />import java.io.FileOutputStream;&nbsp; <br />import java.io.IOException;&nbsp; <br />import java.io.OutputStreamWriter;&nbsp; <br />import java.io.PrintWriter;&nbsp; <br />import javax.servlet.RequestDispatcher;&nbsp; <br />import javax.servlet.ServletContext;&nbsp; <br />import javax.servlet.ServletException;&nbsp; <br />import javax.servlet.ServletOutputStream;&nbsp; <br />import javax.servlet.http.HttpServletRequest;&nbsp; <br />import javax.servlet.http.HttpServletResponse;&nbsp; <br />import javax.servlet.http.HttpServletResponseWrapper;&nbsp; <br />/** <br />&nbsp;* 创建HTML静态页面 <br />&nbsp;* 功能：创建HTML静态页面 <br />&nbsp;* 时间：2009年1011日 <br />&nbsp;* 地点：home <br />&nbsp;* @author mavk <br />&nbsp;* <br />&nbsp;*/&nbsp; <br />public class CreateStaticHTMLPage {&nbsp; <br />&nbsp;&nbsp;&nbsp; /** <br />&nbsp;&nbsp;&nbsp;&nbsp; * 生成静态HTML页面的方法 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param request 请求对象 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param response 响应对象 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param servletContext Servlet上下文 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param fileName 文件名称 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param fileFullPath 文件完整路径 <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param jspPath 需要生成静态文件的JSP路径(相对即可) <br />&nbsp;&nbsp;&nbsp;&nbsp; * @throws IOException <br />&nbsp;&nbsp;&nbsp;&nbsp; * @throws ServletException <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />&nbsp;&nbsp;&nbsp; public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException{&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.setContentType("text/html;charset=gb2312");//设置HTML结果流编码(即HTML文件编码)&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//得到JSP资源&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//用于从ServletOutputStream中接收资源&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final ServletOutputStream servletOuputStream = new ServletOutputStream(){//用于从HttpServletResponse中接收资源&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void write(byte[] b, int off,int len){&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byteArrayOutputStream.write(b, off, len);&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; public void write(int b){&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byteArrayOutputStream.write(b);&nbsp; <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; final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//把转换字节流转换成字符流&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用于从response获取结果流资源(重写了两个方法)&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ServletOutputStream getOutputStream(){&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return servletOuputStream;&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; public PrintWriter getWriter(){&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return printWriter;&nbsp; <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; rd.include(request, httpServletResponse);//发送结果流&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printWriter.flush();//刷新缓冲区，把缓冲区的数据输出&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byteArrayOutputStream.writeTo(fileOutputStream);//把byteArrayOuputStream中的资源全部写入到fileOuputStream中&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fileOutputStream.close();//关闭输出流，并释放相关资源&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; response.sendRedirect(fileName);//发送指定文件流到客户端&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; <br />} <br />&nbsp;</p>
<p><strong><span style="color: #e53333">三：高并发高负载类网站关注点之缓存、负载均衡、存储 </span></strong></p>
<p>缓存是另一个大问题，我一般用memcached来做缓存集群，一般来说部署10台左右就差不多（10g内存池）。需要注意一点，千万不能用使用<br />swap，最好关闭linux的swap。</p>
<p><br />负载均衡/加速<br />&nbsp;<br />可能上面说缓存的时候，有人第一想的是页面静态化，所谓的静态html，我认为这是常识，不属于要点了。页面的静态化随之带来的是静态服务的<br />负载均衡和加速。我认为Lighttped+Squid是最好的方式了。<br />LVS &lt;-------&gt;lighttped====&gt;squid(s) ====lighttpd</p>
<p>上面是我经常用的。注意，我没有用apache，除非特定的需求，否则我不部署apache，因为我一般用php-fastcgi配合lighttpd,<br />性能比apache+mod_php要强很多。</p>
<p>squid的使用可以解决文件的同步等等问题，但是需要注意，你要很好的监控缓存的命中率，尽可能的提高的90%以上。<br />squid和lighttped也有很多的话题要讨论，这里不赘述。</p>
<p><br />存储<br />&nbsp;存储也是一个大问题，一种是小文件的存储，比如图片这类。另一种是大文件的存储，比如搜索引擎的索引，一般单文件都超过2g以上。<br />小文件的存储最简单的方法是结合lighttpd来进行分布。或者干脆使用Redhat的GFS，优点是应用透明，缺点是费用较高。我是指<br />你购买盘阵的问题。我的项目中，存储量是2-10Tb，我采用了分布式存储。这里要解决文件的复制和冗余。<br />这样每个文件有不同的冗余，这方面可以参考google的gfs的论文。<br />大文件的存储，可以参考nutch的方案，现在已经独立为hadoop子项目。(你可以google it)</p>
<p>其他：<br />此外，passport等也是考虑的，不过都属于比较简单的了。<br /><strong><span style="color: #e53333">四：高并发高负载网站的系统架构之图片服务器分离 </span><br /></strong>大家知道，对于Web 服务器来说，不管是Apache、IIS还是其他容器，图片是最消耗资源的，于是我们有必要将图片与页面进行分离，这是基本上大型网站都会采用的策略，他 们都有独立的图片服务器，甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力，并且可以保证系统不会因为图片问题而崩溃，在应用 服务器和图片服务器上，可以进行不同的配置优化，比如apache在配置ContentType的时候可以尽量少支持，尽可能少的LoadModule， 保证更高的系统消耗和执行效率。 </p>
<p><br />利用Apache实现图片服务器的分离<br />缘由： <br />起步阶段的应用，都可能部署在一台服务器上（费用上的原因） <br />第一个优先分离的，肯定是数据库和应用服务器。 <br />第二个分离的，会是什么呢？各有各的考虑，我所在的项目组重点考虑的节约带宽，服务器性能再好，带宽再高，并发来了，也容易撑不住。因此，我这篇文章的重点在这里。这里重点是介绍实践，不一定符合所有情况，供看者参考吧， <br />环境介绍： <br />WEB应用服务器：4CPU双核2G, 内存4G <br />&nbsp; 部署：Win2003/Apache Http Server 2.1/Tomcat6 <br />数据库服务器：4CPU双核2G, 内存4G <br />&nbsp; 部署：Win2003/MSSQL2000 <br />步骤： <br />步骤一：增加2台配置为：2CPU双核2G，内存2G普通服务器，做资源服务器 <br />&nbsp; 部署：Tomcat6，跑了一个图片上传的简单应用，（记得指定web.xml的&lt;distributable/&gt;），并指定域名为res1.***.com,res2.***.com，采用ajp协议 <br />步骤二：修改Apache httpd.conf配置 <br />&nbsp; 原来应用的文件上传功能网址为： <br />&nbsp;&nbsp; 1、/fileupload.html <br />&nbsp;&nbsp; 2、/otherupload.html <br />&nbsp; 在httpd.conf中增加如下配置 </p>
<p>&lt;VirtualHost *:80&gt;&nbsp;&nbsp; <br />&nbsp; ServerAdmin webmaster@***.com&nbsp;&nbsp; <br />&nbsp; ProxyPass /fileupload.html balancer://rescluster/fileupload lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp; ProxyPass /otherupload.html balancer://rescluster/otherupload.html lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp; #&lt;!--负载均衡--&gt;&nbsp;&nbsp; <br />&nbsp; &lt;Proxy balancer://rescluster/&gt;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; BalancerMember ajp://res1.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat1&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; BalancerMember ajp://res2.***.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat2&nbsp;&nbsp; <br />&nbsp; &lt;/Proxy&gt;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&lt;/VirtualHost&gt;&nbsp; <br />步骤三，修改业务逻辑： <br />&nbsp; 所有上传文件在数据库中均采用全url的方式保存，例如产品图片路径存成：http://res1.***.com/upload/20090101/product120302005.jpg </p>
<p>现在，你可以高枕无忧了，带宽不够时，增加个几十台图片服务器，只需要稍微修改一下apache的配置文件，即可。 </p>
<p><strong><span style="color: #e53333">五：高并发高负载网站的系统架构之数据库集群和库表散列</span></strong></p>
<p>大型网站都有复杂的应用，这些应用必须使用数据库，那么在面对大量访问的时候，数据库的瓶颈很快就能显现出来，这时一台数据库将很快无法满足应用，于是我们需要使用数据库集群或者库表散列。<br />　　<br />　　在数据库集群方面，很多数据库都有自己的解决方案，Oracle、Sybase等都有很好的方案，常用的MySQL提供的Master/Slave也是类似的方案，您使用了什么样的DB，就参考相应的解决方案来实施即可。<br />　　<br />　 　上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制，于是我们需要从应用程序的角度来考虑改善系统架构，库表散列是常用并 且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离，不同的模块对应不同的数据库或者表，再按照一定的策略对某个页面或者 功能进行更小的数据库散列，比如用户表，按照用户ID进行表散列，这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的 架构，将论坛的用户、设置、帖子等信息进行数据库分离，然后对帖子、用户按照板块和ID进行散列数据库和表，最终可以在配置文件中进行简单的配置便能让系 统随时增加一台低成本的数据库进来补充系统性能。 </p>
<p><br />集群软件的分类：<br />一般来讲，集群软件根据侧重的方向和试图解决的问题，分为三大类：高性能集群（High performance cluster，HPC）、负载均衡集群（Load balance cluster， LBC），高可用性集群（High availability cluster，HAC）。<br />高性能集群（High performance cluster，HPC），它是利用一个集群中的多台机器共同完成同一件任务，使得完成任务的速度和可靠性都远远高于单机运行的效果。弥补了单机性能上的不足。该集群在天气预报、环境监控等数据量大，计算复杂的环境中应用比较多；<br />负载均衡集群（Load balance cluster， LBC），它是利用一个集群中的多台单机，完成许多并行的小的工作。一般情况下，如果一个应用使用的人多了，那么用户请求的响应时间就会增大，机器的性能也会受到影响，如果使用负载均衡集群，那么集群中任意一台机器都能响应用户的请求，这样集群就会在用户发出服务请求之后，选择当时负载最小，能够提供最好的服务的这台机器来接受请求并相应，这样就可用用集群来增加系统的可用性和稳定性。这类集群在网站中使用较多；<br />高可用性集群（High availability cluster，HAC），它是利用集群中系统 的冗余，当系统中某台机器发生损坏的时候，其他后备的机器可以迅速的接替它来启动服务，等待故障机的维修和返回。最大限度的保证集群中服务的可用性。这类系统一般在银行，电信服务这类对系统可靠性有高的要求的领域有着广泛的应用。<br />2 数据库集群的现状<br />数据库集群是将计算机集群技术引入到数据库中来实现的，尽管各厂商宣称自己的架构如何的完美，但是始终不能改变Oracle当先，大家追逐的事实，在集群的解决方案上Oracle RAC还是领先于包括微软在内的其它数据库厂商，它能满足客户高可用性、高性能、数据库负载均衡和方便扩展的需求。<br />Oracle&#8217;s Real Application Cluster (RAC)<br />Microsoft SQL Cluster Server (MSCS)<br />IBM&#8217;s DB2 UDB High Availability Cluster(UDB)<br />Sybase ASE High Availability Cluster (ASE)<br />MySQL High Availability Cluster (MySQL CS)<br />基于IO的第三方HA(高可用性)集群<br />当前主要的数据库集群技术有以上六大类，有数据库厂商自己开发的；也有第三方的集群公司开发的；还有数据库厂商与第三方集群公司合作开发的，各类集群实现的功能及架构也不尽相同。<br />RAC（Real Application Cluster，真正应用集群）是Oracle9i数据库中采用的一项新技术，也是Oracle数据库支持网格计算环境的核心技术。它的出现解决了传统数据库应用中面临的一个重要问题：高性能、高可伸缩性与低价格之间的矛盾。在很长一段时间里，甲骨文都以其实时应用集群技术(Real Application Cluster，RAC)统治着集群数据库市场</p>
<p><strong><span style="color: #e53333">六：高并发高负载网站的系统架构之缓存 </span></strong></p>
<p>缓存一词搞技术的都接触过，很多地方用到缓存。网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。 <br />　　架构方面的缓存，对Apache比较熟悉的人都能知道Apache提供了自己的缓存模块，也可以使用外加的Squid模块进行缓存，这两种方式均可以有效的提高Apache的访问响应能力。<br />　 　网站程序开发方面的缓存，Linux上提供的Memory Cache是常用的缓存接口，可以在web开发中使用，比如用Java开发的时候就可以调用MemoryCache对一些数据进行缓存和通讯共享，一些大 型社区使用了这样的架构。另外，在使用web语言开发的时候，各种语言基本都有自己的缓存模块和方法，PHP有Pear的Cache模块，Java就更多 了，.net不是很熟悉，相信也肯定有。 </p>
<p>&nbsp;</p>
<p>Java开源缓存框架 <br />&nbsp;JBossCache/TreeCache JBossCache是一个复制的事务处理缓存，它允许你缓存企业级应用数据来更好的改善性能。缓存数据被自动复制，让你轻松进行Jboss服务器之间的集群工作。JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务，当然，它也能独立运行。 JBossCache包括两个模块：TreeCache和TreeCacheAOP。 TreeCache --是一个树形结构复制的事务处理缓存。 TreeCacheAOP --是一个&#8220;面向对象&#8221;缓存，它使用AOP来动态管理POJO<br />OSCache OSCache标记库由OpenSymphony设计，它是一种开创性的JSP定制标记应用，提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架，OSCache能用于任何Java应用程序的普通的缓存解决方案。OSCache有以下特点：缓存任何对象，你可以不受限制的缓存部分jsp页面或HTTP请求，任何java对象都可以缓存。 拥有全面的API--OSCache API给你全面的程序来控制所有的OSCache特性。 永久缓存--缓存能随意的写入硬盘，因此允许昂贵的创建（expensive-to-create）数据来保持缓存，甚至能让应用重启。 支持集群--集群缓存数据能被单个的进行参数配置，不需要修改代码。 缓存记录的过期--你可以有最大限度的控制缓存对象的过期，包括可插入式的刷新策略（如果默认性能不需要时）。<br />JCACHE JCACHE是一种即将公布的标准规范（JSR 107），说明了一种对Java对象临时在内存中进行缓存的方法，包括对象的创建、共享访问、假脱机（spooling）、失效、各JVM的一致性等。它可被用于缓存JSP内最经常读取的数据，如产品目录和价格列表。利用JCACHE，多数查询的反应时间会因为有缓存的数据而加快（内部测试表明反应时间大约快15倍）。<br />Ehcache Ehcache出自Hibernate，在Hibernate中使用它作为数据缓存的解决方案。<br />Java Caching System JCS是Jakarta的项目Turbine的子项目。它是一个复合式的缓冲工具。可以将对象缓冲到内存、硬盘。具有缓冲对象时间过期设定。还可以通过JCS构建具有缓冲的分布式构架，以实现高性能的应用。 对于一些需要频繁访问而每访问一次都非常消耗资源的对象，可以临时存放在缓冲区中，这样可以提高服务的性能。而JCS正是一个很好的缓冲工具。缓冲工具对于读操作远远多于写操作的应用性能提高非常显著。<br />SwarmCache SwarmCache是一个简单而功能强大的分布式缓存机制。它使用IP组播来有效地在缓存的实例之间进行通信。它是快速提高集群式Web应用程序的性能的理想选择。<br />ShiftOne ShiftOne Object Cache这个Java库提供了基本的对象缓存能力。实现的策略有先进先出（FIFO），最近使用（LRU），最不常使用（LFU）。所有的策略可以最大化元素的大小，最大化其生存时间。<br />WhirlyCache Whirlycache是一个快速的、可配置的、存在于内存中的对象的缓存。它能够通过缓存对象来加快网站或应用程序的速度，否则就必须通过查询数据库或其他代价较高的处理程序来建立。<br />Jofti Jofti可对在缓存层中(支持EHCache，JBossCache和OSCache)的对象或在支持Map接口的存储结构中的对象进行索引与搜索。这个框架还为对象在索引中的增删改提供透明的功能同样也为搜索提供易于使用的查询功能。<br />cache4j cache4j是一个有简单API与实现快速的Java对象缓存。它的特性包括：在内存中进行缓存，设计用于多线程环境，两种实现：同步与阻塞，多种缓存清除策略：LFU, LRU, FIFO，可使用强引用(strong reference)与软引用(soft reference)存储对象。<br />&nbsp;Open Terracotta 一个JVM级的开源群集框架，提供：HTTP Session复制，分布式缓存，POJO群集，跨越群集的JVM来实现分布式应用程序协调(采用代码注入的方式，所以你不需要修改任何)。<br />&nbsp;sccache SHOP.COM使用的对象缓存系统。sccache是一个in-process cache和二级、共享缓存。它将缓存对象存储到磁盘上。支持关联Key，任意大小的Key和任意大小的数据。能够自动进行垃圾收集。<br />&nbsp;Shoal Shoal是一个基于Java可扩展的动态集群框架，能够为构建容错、可靠和可用的Java应用程序提供了基础架构支持。这个框架还可以集成到不希望绑定到特定通信协议，但需要集群和分布式系统支持的任何Java产品中。Shoal是GlassFish和JonAS应用服务器的集群引擎。<br />Simple-Spring-Memcached Simple-Spring-Memcached，它封装了对MemCached的调用，使MemCached的客户端开发变得超乎寻常的简单。<br />&nbsp;</p><br /><br /><br /><br /><a href="http://www.ablanxue.com/prone_1020_1.html">http://www.ablanxue.com/prone_1020_1.html</a> <img src ="http://www.blogjava.net/stevenjohn/aggbug/396808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/stevenjohn/" target="_blank">abin</a> 2013-03-21 15:53 <a href="http://www.blogjava.net/stevenjohn/archive/2013/03/21/396808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>