Java多线程与并发库高级应用-工具类介绍

java.util.concurrent.Lock

1、Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,
锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。

  lock替代synchronized

  

Java多线程与并发库高级应用-工具类介绍
class Outputer {
        Lock lock = new ReentrantLock();
        public void output(String name) {
            int len = name.length();
            lock.lock();    
            try{
                for (int i = 0; i < len; i++) {
                    char c = name.charAt(i);
                    System.out.print(c);
                }
            }finally{
                lock.unlock();  //这里防止内部代码出现异常,即无论如何最后都会释放锁
            }
            lock.unlock();
            System.out.println();
        }
}
Java多线程与并发库高级应用-工具类介绍

 

售票系统

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    Ticket ticket </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Ticket();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口1售票"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口2售票"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口3售票"<span style="color: #000000">).start();</br></br>
}

}

class Ticket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
    </span><span style="color: #0000ff">while</span> (<span style="color: #0000ff">true</span><span style="color: #000000">) {</br>
        lock.lock();</br>
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
            </span><span style="color: #0000ff">if</span> (ticket &gt; 0<span style="color: #000000">) {</br>
                Thread.sleep(</span>20<span style="color: #000000">);</br>
                System.out.println(Thread.currentThread().getName()</br>
                        </span>+ ",余票量:" + ticket--<span style="color: #000000">);</br>
            }</br>
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
            e.printStackTrace();</br>
        } </span><span style="color: #0000ff">finally</span><span style="color: #000000"> {</br>
            lock.unlock();</br>
        }</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

2、读写锁:

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。
* 如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;
* 如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。
* 总之,读的时候上读锁,写的时候上写锁!

Java多线程与并发库高级应用-工具类介绍
/* 面试题:3个线程读,3个线程写 同一个数据
 */
public class ReadWriteLockTest {
    public static void main(String[] args) {
        final Queue3 queue = new Queue3();
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;3;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span><span style="color: #000000">){</br>
                    queue.get();</br>
                }</br>
            }</br>
        }).start();</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                queue.set(</span><span style="color: #0000ff">new</span> Random().nextInt(10000<span style="color: #000000">));</br>
            }</br>
        }).start();</br>
    }</br>
}</br></br>

}

class Queue3{
private Object data = null; //共享数据 ,只能有一个线程写该数据,但可以有多个线程同时读
ReadWriteLock rwl = new ReentrantReadWriteLock(); //读写锁
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> get(){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        rwl.readLock().lock();  </span><span style="color: #008000">//</span><span style="color: #008000">上读锁 可以有多个线程同时读</span></br>
        System.out.println(Thread.currentThread().getName() + " be ready to read data!"<span style="color: #000000">);</br>
        Thread.sleep((</span><span style="color: #0000ff">long</span>)Math.random() * 1000<span style="color: #000000">);</br>
        System.out.println(Thread.currentThread().getName() </span>+ " have read data : "+<span style="color: #000000"> data);</br>
    } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        rwl.readLock().unlock();  </span><span style="color: #008000">//</span><span style="color: #008000">释放读锁</span></br>

}
}
public void set(Object data){
try {
rwl.writeLock().lock();
//添加写锁,保证只能有一个线程进行写操作
System.out.println(Thread.currentThread().getName() + " be read to write data: "+ data);
Thread.sleep((
long)Math.random() * 1000);
this.data = data;
System.out.println(Thread.currentThread().getName()
+ "has write data");
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally{
rwl.writeLock().unlock();
//释放写锁
}
}
}

Java多线程与并发库高级应用-工具类介绍

 简单的读写锁示例

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriteLock {
public static void main(String[] args) {
final ReadWriteLockDemo demo = new ReadWriteLockDemo();
new Thread(new Runnable(){
@Override
public void run() {
demo.set(
new Random().nextInt(5000));
}
},
"Write").start();
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;100;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                demo.get();</br>
            }</br>
        }, </span>"Read"<span style="color: #000000">).start();</br>
    }</br>
}</br>

}

class ReadWriteLockDemo{
private int number = 0;
</span><span style="color: #0000ff">private</span> ReadWriteLock lock = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantReadWriteLock();</br></br>

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> get(){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        lock.readLock().lock();</br>
        System.out.println(Thread.currentThread().getName() </span>+" "+<span style="color: #000000">number);</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.readLock().unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> set(<span style="color: #0000ff">int</span><span style="color: #000000"> number){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        lock.writeLock().lock();</br>
        </span><span style="color: #0000ff">this</span>.number =<span style="color: #000000"> number;</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.writeLock().unlock();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

 Hibernate的一个面试题:

  User user = session.load(id,User.class);

  User user = session.get(id,User.class);

  以上两个的却别。

  get()方式,直接查询数据库,如果查询到赋值给User对象,如果没有查询到则返回为null

  load()方式,实际上是从User的一个代理中获取, User$Proxy中包含有一个真实的User对象,当调用load()时,如果成员变量User为null,则从数据库查询将记录返回并给User赋值,当load()时User不为null,则直接返回User对象

Java多线程与并发库高级应用-工具类介绍
/**
 * 面试题: 设计一个缓存系统
 * @author Administrator
 *
 */
public class CacheDemo {
Map</span>&lt;String, Object&gt; cache = <span style="color: #0000ff">new</span> HashMap&lt;String, Object&gt;<span style="color: #000000">();</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>

}

</span><span style="color: #0000ff">private</span> ReadWriteLock rwl = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantReadWriteLock();</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> Object getData(String key){</br>
    rwl.readLock().lock(); </br>
    Object value </span>= <span style="color: #0000ff">null</span><span style="color: #000000">;</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        value </span>=<span style="color: #000000"> cache.get(key);</br>
        </span><span style="color: #0000ff">if</span>(value == <span style="color: #0000ff">null</span><span style="color: #000000">){</br>
            rwl.readLock().unlock();</br>
            rwl.writeLock().lock();</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">if</span>(value == <span style="color: #0000ff">null</span><span style="color: #000000">){  //防止后边线程加载数据,使用双端检测机制</br>
                    value </span>= "xxx"; <span style="color: #008000">//</span><span style="color: #008000">queryDB</span></br>

cache.put(key, value);
}
}
finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}
catch (Exception e) {
}
finally{
rwl.readLock().unlock();
}
return value;
}

}

Java多线程与并发库高级应用-工具类介绍

ReadWriteLock javaAPI中有缓存的代码:

class CachedData {
   Object data;
   volatile boolean cacheValid;
   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
// Recheck state because another thread might have acquired
// write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
rwl.writeLock().unlock(); // Unlock write, still hold read
}

 use(data);</br>
 rwl.readLock().unlock();</br>

}
}

3、Condition 实现线程通信

传统的线程通信方式

Java多线程与并发库高级应用-工具类介绍
/*
 * 传统线程通信
 * 主线程和子线程分别打印 100次 和 10次,循环50次
 */
public class TraditionalThreadCommunication2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Buiness buiness = <span style="color: #0000ff">new</span><span style="color: #000000"> Buiness();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
                buiness.sub(i);</br>
            }</br>
        }</br>
    }).start();</br></br>
    
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
        buiness.main(i);</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Buiness{</br>
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">boolean</span> isShouldSub = <span style="color: #0000ff">false</span>;  <span style="color: #008000">//</span><span style="color: #008000">主线程先打印</span></br>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span> j){ <span style="color: #008000">//</span><span style="color: #008000">进行同步,防止在打印时被其他线程干扰</span></br>
        <span style="color: #0000ff">while</span>(isShouldSub){  <span style="color: #008000">//</span><span style="color: #008000">这里使用while 防止假唤醒</span></br>
            <span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">this</span>.wait();  <span style="color: #008000">//</span><span style="color: #008000">wait() 和 notify() 必须出现在synchronized同步中</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=100;i++<span style="color: #000000">){</br>
            System.out.println(</span>"main thread print "+ i + " loop of " +<span style="color: #000000"> j);</br>
        }</br>
        isShouldSub </span>= <span style="color: #0000ff">true</span><span style="color: #000000">;</br>
        </span><span style="color: #0000ff">this</span><span style="color: #000000">.notify();</br>
    }</br>
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> sub(<span style="color: #0000ff">int</span><span style="color: #000000"> j){</br>
        </span><span style="color: #0000ff">while</span>(!<span style="color: #000000">isShouldSub){</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">this</span><span style="color: #000000">.wait();</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1 ; i&lt;=10;i++<span style="color: #000000">){</br>
            System.out.println(</span>"sub thread print "+ i + " loop of " +<span style="color: #000000"> j);</br>
        }</br>
        isShouldSub </span>= <span style="color: #0000ff">false</span><span style="color: #000000">;</br>
        </span><span style="color: #0000ff">this</span><span style="color: #000000">.notify();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

将上述程序改写为使用Condition

Java多线程与并发库高级应用-工具类介绍
/*
 * 传统线程通信
 * 主线程和子线程分别打印 100次 和 10次,循环50次
 * 改写成使用 Condition 的方式
 */
public class TraditionalThreadCommunication2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Buiness buiness = <span style="color: #0000ff">new</span><span style="color: #000000"> Buiness();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
                buiness.sub(i);</br>
            }</br>
        }</br>
    }).start();</br></br>
    
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
        buiness.main(i);</br>
    }</br>
}</br></br>

</span><span style="color: #008000">/**</span><span style="color: #008000"></br>
 * 将程序改写为使用Lock&amp;Condition的方式进行 同步和通信</br>
 * </span><span style="color: #808080">@author</span><span style="color: #008000"> Administrator</br>
 *</br>
 </span><span style="color: #008000">*/</span></br></br>
<span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Buiness{
    Lock lock </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantLock();</br>
    Condition condition </span>=<span style="color: #000000"> lock.newCondition();</br>
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">boolean</span> isShouldSub = <span style="color: #0000ff">false</span>;  <span style="color: #008000">//</span><span style="color: #008000">主线程先打印</span>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span> j){ <span style="color: #008000">//</span><span style="color: #008000">进行同步,防止在打印时被其他线程干扰</span>

lock.lock();
try {
while(isShouldSub){ //这里使用while 防止假唤醒
try {
condition.await();
// this.wait(); //wait() 和 notify() 必须出现在同步监视器内部中
} catch (Exception e) {
e.printStackTrace();
}
}
for(int i = 1;i<=100;i++){
System.out.println(
"main thread print "+ i + " loop of " + j);
}
isShouldSub
= true;
condition.signal();
// this.notify();
} finally {
lock.unlock();
}
}
public void sub(int j){
lock.lock();
try {
while(!isShouldSub){
try {
condition.await();
// this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
for(int i = 1 ; i<=10;i++){
System.out.println(
"sub thread print "+ i + " loop of " + j);
}
isShouldSub
= false;
condition.signal();
// this.notify();
} finally{
lock.unlock();
}
}
}

}

Java多线程与并发库高级应用-工具类介绍

main thread print 1 loop of 1
main thread print 2 loop of 1
main thread print 3 loop of 1
main thread print 4 loop of 1
main thread print 5 loop of 1
main thread print 6 loop of 1
main thread print 7 loop of 1
...
main thread print 99 loop of 1
main thread print 100 loop of 1
sub thread print 1 loop of 1
sub thread print 2 loop of 1
sub thread print 3 loop of 1
sub thread print 4 loop of 1
sub thread print 5 loop of 1
sub thread print 6 loop of 1
sub thread print 7 loop of 1
sub thread print 8 loop of 1
sub thread print 9 loop of 1
sub thread print 10 loop of 1
main thread print 1 loop of 2
main thread print 2 loop of 2
main thread print 3 loop of 2
main thread print 4 loop of 2
main thread print 5 loop of 2
main thread print 6 loop of 2
main thread print 7 loop of 2
main thread print 8 loop of 2
main thread print 9 loop of 2
...
main thread print 99 loop of 2
main thread print 100 loop of 2
sub thread print 1 loop of 2
sub thread print 2 loop of 2
sub thread print 3 loop of 2
sub thread print 4 loop of 2
sub thread print 5 loop of 2
sub thread print 6 loop of 2
sub thread print 7 loop of 2
sub thread print 8 loop of 2
sub thread print 9 loop of 2
sub thread print 10 loop of 2
main thread print 1 loop of 3
main thread print 2 loop of 3
main thread print 3 loop of 3

...

使用Condition比传统的好处

可以实现多路Condition ,在javaAPI中有

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

final Object[] items = new Object[100];
int putptr, takeptr, count;

public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}

public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}

使用多路Condition,可以扩展上述的一个例子,老大打印完 -> 老二   老二-> 老三  老三-> 老大  老大-> 老二...

Java多线程与并发库高级应用-工具类介绍
/**
 * 第一个线程循环100次,第二个线程循环10次,第三个线程循环20次,如此循环50次,请写出程序 这里使用Condition
 * 
 * @author Administrator
 * 
 */
public class ThreeConditionCommunication {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Business2 business = <span style="color: #0000ff">new</span><span style="color: #000000"> Business2();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
                business.sub2(i);</br>
            }</br>
        }</br>
    }).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
                business.sub3(i);</br>
            }</br>
        }</br>
    }).start();</br></br>

    </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
        business.main(i);</br>
    }</br>
}</br></br>

}

class Business2 {
Lock lock
= new ReentrantLock();
Condition condition1
= lock.newCondition();
Condition condition2
= lock.newCondition();
Condition condition3
= lock.newCondition();
private int shoudeSub = 1;
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sub2(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 2) { <span style="color: #008000">//</span><span style="color: #008000"> 这里也可以用 if ,用while比较好一些 As in the one argument</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> version, interrupts and spurious wakeups are</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> possible, and this method should always be</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> used in a loop</span></br>
            <span style="color: #0000ff">try</span> { <span style="color: #008000">//</span><span style="color: #008000"> 防止线程有可能被假唤醒 (while放在这里提现了水准)</span></br>
                condition2.await();  <span style="color: #008000">//</span><span style="color: #008000">等待</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 100; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"sub2 thread sequence of " + j + ", loop of " +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 3<span style="color: #000000">;</br>
        condition3.signal();</span><span style="color: #008000">//</span><span style="color: #008000">唤醒</span></br>
    } <span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sub3(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 3) { <span style="color: #008000">//</span><span style="color: #008000"> 这里也可以用 if ,用while比较好一些 As in the one argument</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> version, interrupts and spurious wakeups are</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> possible, and this method should always be</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> used in a loop</span></br>
            <span style="color: #0000ff">try</span> { <span style="color: #008000">//</span><span style="color: #008000"> 防止线程有可能被假唤醒 (while放在这里提现了水准)</span></br>
                condition3.await();  <span style="color: #008000">//</span><span style="color: #008000">等待</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 20; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"sub3 thread sequence of " + j + ", loop of " +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 1<span style="color: #000000">;</br>
        condition1.signal();</span><span style="color: #008000">//</span><span style="color: #008000">唤醒</span></br>
    } <span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 1<span style="color: #000000">) {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                condition1.await();</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 10; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"main thread sequence of " + j + ", loop of "</br>
                    +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 2<span style="color: #000000">;</br>
        condition2.signal();</br>
    } </span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #008000">/**</span><span style="color: #008000"></br>
 * </br>
 * synchronized (obj) { 这里的obj与obj.wait必须相同,否则会抛异常 while (&lt;condition does</br>
 * not hold&gt;) obj.wait(); ... // Perform action appropriate to condition }</br>
 </span><span style="color: #008000">*/</span><span style="color: #000000"></br>

}

Java多线程与并发库高级应用-工具类介绍

Condition的一个例子:

 编写一个程序,开启3个线程 ,这三个线程的ID分别为 A,B, C,每个线程将自己的ID 在屏幕上打印10遍,要求输出的结果必须按顺序显示。

如:ABCABCABC.....依次递归

这里实现了一个比题目稍微难得例子,A 打印10次,B打印20次 ,C打印5次依次递归20次。

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestAlternative {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Alternative alternative = <span style="color: #0000ff">new</span><span style="color: #000000"> Alternative();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopA(i);</br>
            }</br>
        }</br>
    },</span>"A"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopB(i);</br>
            }</br>
        }</br>
    },</span>"B"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopC(i);</br>
                System.out.println(</span>"-----------------"<span style="color: #000000">);</br>
            }</br>
        }</br>
    },</span>"C"<span style="color: #000000">).start();</br>
    </br>
}</br>
}
class Alternative{
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> number = 1<span style="color: #000000">;</br>
</span><span style="color: #0000ff">private</span> Lock lock = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantLock();</br>
</span><span style="color: #0000ff">private</span> Condition condition1 =<span style="color: #000000"> lock.newCondition();</br>
</span><span style="color: #0000ff">private</span> Condition condition2 =<span style="color: #000000"> lock.newCondition();</br>
</span><span style="color: #0000ff">private</span> Condition condition3 =<span style="color: #000000"> lock.newCondition();</br></br>

</span><span style="color: #0000ff">void</span> loopA(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 1<span style="color: #000000">){</br>
            condition1.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=10;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 2<span style="color: #000000">;</br>
        condition2.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000"> {</br>
        lock.unlock();</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">void</span> loopB(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 2<span style="color: #000000">){</br>
            condition2.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 3<span style="color: #000000">;</br>
        condition3.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
        </br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">void</span> loopC(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 3<span style="color: #000000">){</br>
            condition3.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=5;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 1<span style="color: #000000">;</br>
        condition1.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
        </br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

java5的Semaphere同步工具

  Semaphore实现信号灯

  Semaphore可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。

  假设一个文件同时可以被3个人访问,来了5个人,同时只有3个访问。3个中任何一个出来后,等待的就可以进去了。

Java多线程与并发库高级应用-工具类介绍
public class SemaphoreTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>
    ExecutorService service </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span>  Semaphore sp = <span style="color: #0000ff">new</span> Semaphore(3<span style="color: #000000">);  //还有一个构造方法,<code><strong><a>Semaphore</a></strong>(int permits, boolean fair)</code>  fair参数为true表示谁先来谁先进,一种公平的原则 </br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i=0;i&lt;10;i++<span style="color: #000000">){</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
                </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run(){</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    sp.acquire();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e1) {</br>
                    e1.printStackTrace();</br>
                }</br>
                System.out.println(</span>"线程" + Thread.currentThread().getName() + </br>
                        "进入,当前已有" + (3-sp.availablePermits()) + "个并发"<span style="color: #000000">);</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>)(Math.random()*10000<span style="color: #000000">));</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                    e.printStackTrace();</br>
                }</br>
                System.out.println(</span>"线程" + Thread.currentThread().getName() + </br>
                        "即将离开"<span style="color: #000000">);                    </br>
                sp.release();
                </span><span style="color: #008000">//</span><span style="color: #008000">下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元</span></br>
                System.out.println("线程" + Thread.currentThread().getName() + 
                        "已离开,当前已有" + (3-sp.availablePermits()) + "个并发"<span style="color: #000000">);                    </br>
            }</br>
        };</br>
        service.execute(runnable);           </br> 
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了 "锁",再由另外一个线程释放"锁",这可应用于死锁恢复的一些场合。

java5 的CyclicBarrier同步工具

Java多线程与并发库高级应用-工具类介绍
/**
 * 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面,
 * 这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,
 * 再同时出发到公园游玩,在指定地点集合后再同时开始就餐,…。
 * @author Administrator
 *
 */
public class CyclicBarrierTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService threadPool </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> CyclicBarrier cb = <span style="color: #0000ff">new</span> CyclicBarrier(3<span style="color: #000000">);</br>
    </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; 3; i++<span style="color: #000000">) {</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                                    </span>+ "即将到达集合点1,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br></br>
                    
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                            </span>+ "即将到达集合点2,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br></br>
                    
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                            </span>+ "即将到达集合点3,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                    </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
};
threadPool.execute(runnable);
}
threadPool.shutdown();
}

}

Java多线程与并发库高级应用-工具类介绍

java5的CountDownLatch同步工具

  CountDownLatch : 闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行

  CountDownLatch应用1:比如要统计5个线程并发的运行时间,即线程的开始时间与最后一个线程的运行结束时间的间隔时间。

  

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>

    CountDownLatch latch </span>= <span style="color: #0000ff">new</span> CountDownLatch(5<span style="color: #000000">);</br>
    LatchDemo2 ld </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> LatchDemo2(latch);</br></br>
    
    </span><span style="color: #0000ff">long</span> start =<span style="color: #000000"> System.currentTimeMillis();</br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;5;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span><span style="color: #000000"> Thread(ld).start();</br></br>
    }
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        latch.await();   </span><span style="color: #008000">//</span><span style="color: #008000">先执行完成的线程需要等待还没有执行完的线程</span></br>
    } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
        e.printStackTrace();</br>
    }</br></br>
    
    </span><span style="color: #0000ff">long</span> end  =<span style="color: #000000"> System.currentTimeMillis();</br>
    System.out.println(</span>"cost: "+ (end -<span style="color: #000000"> start));</br>
}</br>
}

class LatchDemo2 implements Runnable{
private CountDownLatch latch;
</span><span style="color: #0000ff">public</span><span style="color: #000000"> LatchDemo2(CountDownLatch latch) {</br>
    </span><span style="color: #0000ff">this</span>.latch =<span style="color: #000000"> latch;</br>
}</br></br>

@Override</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
try { synchronized(this){ for(int i = 0;i<50000;i++){ //找出50000以内的所有偶数 if(i % 2 == 0){ System.out.println(i); } } } } finally{ latch.countDown(); //为了让这一句一定执行可以放在finally中 } } }
Java多线程与并发库高级应用-工具类介绍

  还可以应用于计算所有种类商品的平均销售总和,平均销售时间等,如果使用单线程计算效率非常低,相当于是串行计算。可以使用并行计算,按照商品种类进行区分并行的计算。可以将最终的每个线程的计算结果在进行汇总,可以得出最终的的总的销售数据,这就可以使用CountDownLatch进行操作,可以大幅度提高效率。(京东)

Java多线程与并发库高级应用-工具类介绍

应用:运动员跑步比赛,得到最终的排名需要在所有运动员都完成之后,公布最终的结果。

Java多线程与并发库高级应用-工具类介绍
/**
 * 犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减一,
 * 当计数器到达0时,则所有等待者或单个等待者开始执行。
 * 可以实现一个人(也可以是多个人)等待其他所有人都来通知他,可以实现一个人通知多个人的效果,
 * 类似裁判一声口令,运动员同时开始奔跑,或者所有运动员都跑到
 * 终点后裁判才可以公布结果。还可以实现一个计划需要多个领导都签字后
 * 才能继续向下实施的情况
 * @author Administrator
 *
 */
public class CountDownLetchTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService executorService </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> CountDownLatch cdOrder = <span style="color: #0000ff">new</span> CountDownLatch(1); <span style="color: #008000">//</span><span style="color: #008000">计数器初始值 1</span></br>
    <span style="color: #0000ff">final</span> CountDownLatch cdAnswer = <span style="color: #0000ff">new</span> CountDownLatch(3<span style="color: #000000">);</br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;3;i++<span style="color: #000000">){</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br></br>
            
            @Override
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"正准备接受命令"<span style="color: #000000">);</br>
                    cdOrder.await();</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"已接受命令"<span style="color: #000000">);</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>)(Math.random()*10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"回应命令处理结果"<span style="color: #000000">);</br>
                    cdAnswer.countDown();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                    </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
};
executorService.execute(runnable);
}
try {
Thread.sleep((
long)(Math.random()*10000));
System.out.println(
"线程"+Thread.currentThread().getName()
+"即将发布命令");
cdOrder.countDown();
//计数器数值减 1
System.out.println("线程"+Thread.currentThread().getName()
+"已发送命令,正在等待结果");
cdAnswer.await();
System.out.println(
"线程"+Thread.currentThread().getName()
+"已收到所有响应结果");
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
}

Java多线程与并发库高级应用-工具类介绍

 java 中CycliBarriar 和 CountDownLatch 有什么区别?

  这两个的区别是CyclicBarrier 可以重复使用已经通过的障碍,而 CountdownLatch 不能重复使用。

java5的Exchanger同步工具

Java多线程与并发库高级应用-工具类介绍
/**
 * 用于实现两个人之间的数据交换,每个人在完成一定的事物后想与对方交换数据,第一个先拿出数据的人将
 * 一直等待第二个人拿着数据到来时,才能彼此交换数据。
 * @author Administrator
 *
 */
public class ExchangerTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService executorService </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> Exchanger exchanger = <span style="color: #0000ff">new</span><span style="color: #000000"> Exchanger();</br>
    executorService.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br></br>

        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                String data1 </span>= "aaa"<span style="color: #000000">;</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "正在把数据" + data1 + "换出去"<span style="color: #000000">);</br>
                Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                String data2 </span>=<span style="color: #000000"> (String) exchanger.exchange(data1);</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "换回的数据为 " +<span style="color: #000000"> data2);</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
});
executorService.execute(
new Runnable() {

        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                String data1 </span>= "bbb"<span style="color: #000000">;</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "正在把数据" + data1 + "换出去"<span style="color: #000000">);</br>
                Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                String data2 </span>=<span style="color: #000000"> (String) exchanger.exchange(data1);</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "换回的数据为 " +<span style="color: #000000"> data2);</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
});
}

}

Java多线程与并发库高级应用-工具类介绍

打印结果为:

线程 pool-1-thread-1正把数据 aaa 换出去

线程 pool-1-thread-2正把数据 bbb 换出去

线程 pool-1-thread-2换回的数据为 aaa

线程 pool-1-thread-1换回的数据为 bbb

java.util.concurrent.Lock

1、Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,
锁本身也应该是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。

  lock替代synchronized

  

Java多线程与并发库高级应用-工具类介绍
class Outputer {
        Lock lock = new ReentrantLock();
        public void output(String name) {
            int len = name.length();
            lock.lock();    
            try{
                for (int i = 0; i < len; i++) {
                    char c = name.charAt(i);
                    System.out.print(c);
                }
            }finally{
                lock.unlock();  //这里防止内部代码出现异常,即无论如何最后都会释放锁
            }
            lock.unlock();
            System.out.println();
        }
}
Java多线程与并发库高级应用-工具类介绍

 

售票系统

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    Ticket ticket </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Ticket();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口1售票"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口2售票"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(ticket, "窗口3售票"<span style="color: #000000">).start();</br></br>
}

}

class Ticket implements Runnable {
private int ticket = 100;
private Lock lock = new ReentrantLock();
@Override
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
    </span><span style="color: #0000ff">while</span> (<span style="color: #0000ff">true</span><span style="color: #000000">) {</br>
        lock.lock();</br>
        </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
            </span><span style="color: #0000ff">if</span> (ticket &gt; 0<span style="color: #000000">) {</br>
                Thread.sleep(</span>20<span style="color: #000000">);</br>
                System.out.println(Thread.currentThread().getName()</br>
                        </span>+ ",余票量:" + ticket--<span style="color: #000000">);</br>
            }</br>
        } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
            e.printStackTrace();</br>
        } </span><span style="color: #0000ff">finally</span><span style="color: #000000"> {</br>
            lock.unlock();</br>
        }</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

2、读写锁:

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。
* 如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;
* 如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。
* 总之,读的时候上读锁,写的时候上写锁!

Java多线程与并发库高级应用-工具类介绍
/* 面试题:3个线程读,3个线程写 同一个数据
 */
public class ReadWriteLockTest {
    public static void main(String[] args) {
        final Queue3 queue = new Queue3();
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;3;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">while</span>(<span style="color: #0000ff">true</span><span style="color: #000000">){</br>
                    queue.get();</br>
                }</br>
            }</br>
        }).start();</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                queue.set(</span><span style="color: #0000ff">new</span> Random().nextInt(10000<span style="color: #000000">));</br>
            }</br>
        }).start();</br>
    }</br>
}</br></br>

}

class Queue3{
private Object data = null; //共享数据 ,只能有一个线程写该数据,但可以有多个线程同时读
ReadWriteLock rwl = new ReentrantReadWriteLock(); //读写锁
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> get(){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        rwl.readLock().lock();  </span><span style="color: #008000">//</span><span style="color: #008000">上读锁 可以有多个线程同时读</span></br>
        System.out.println(Thread.currentThread().getName() + " be ready to read data!"<span style="color: #000000">);</br>
        Thread.sleep((</span><span style="color: #0000ff">long</span>)Math.random() * 1000<span style="color: #000000">);</br>
        System.out.println(Thread.currentThread().getName() </span>+ " have read data : "+<span style="color: #000000"> data);</br>
    } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        rwl.readLock().unlock();  </span><span style="color: #008000">//</span><span style="color: #008000">释放读锁</span></br>

}
}
public void set(Object data){
try {
rwl.writeLock().lock();
//添加写锁,保证只能有一个线程进行写操作
System.out.println(Thread.currentThread().getName() + " be read to write data: "+ data);
Thread.sleep((
long)Math.random() * 1000);
this.data = data;
System.out.println(Thread.currentThread().getName()
+ "has write data");
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally{
rwl.writeLock().unlock();
//释放写锁
}
}
}

Java多线程与并发库高级应用-工具类介绍

 简单的读写锁示例

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TestReadWriteLock {
public static void main(String[] args) {
final ReadWriteLockDemo demo = new ReadWriteLockDemo();
new Thread(new Runnable(){
@Override
public void run() {
demo.set(
new Random().nextInt(5000));
}
},
"Write").start();
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;100;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            @Override</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                demo.get();</br>
            }</br>
        }, </span>"Read"<span style="color: #000000">).start();</br>
    }</br>
}</br>

}

class ReadWriteLockDemo{
private int number = 0;
</span><span style="color: #0000ff">private</span> ReadWriteLock lock = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantReadWriteLock();</br></br>

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> get(){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        lock.readLock().lock();</br>
        System.out.println(Thread.currentThread().getName() </span>+" "+<span style="color: #000000">number);</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.readLock().unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> set(<span style="color: #0000ff">int</span><span style="color: #000000"> number){</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        lock.writeLock().lock();</br>
        </span><span style="color: #0000ff">this</span>.number =<span style="color: #000000"> number;</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.writeLock().unlock();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

 Hibernate的一个面试题:

  User user = session.load(id,User.class);

  User user = session.get(id,User.class);

  以上两个的却别。

  get()方式,直接查询数据库,如果查询到赋值给User对象,如果没有查询到则返回为null

  load()方式,实际上是从User的一个代理中获取, User$Proxy中包含有一个真实的User对象,当调用load()时,如果成员变量User为null,则从数据库查询将记录返回并给User赋值,当load()时User不为null,则直接返回User对象

Java多线程与并发库高级应用-工具类介绍
/**
 * 面试题: 设计一个缓存系统
 * @author Administrator
 *
 */
public class CacheDemo {
Map</span>&lt;String, Object&gt; cache = <span style="color: #0000ff">new</span> HashMap&lt;String, Object&gt;<span style="color: #000000">();</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>

}

</span><span style="color: #0000ff">private</span> ReadWriteLock rwl = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantReadWriteLock();</br>
</span><span style="color: #0000ff">public</span><span style="color: #000000"> Object getData(String key){</br>
    rwl.readLock().lock(); </br>
    Object value </span>= <span style="color: #0000ff">null</span><span style="color: #000000">;</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        value </span>=<span style="color: #000000"> cache.get(key);</br>
        </span><span style="color: #0000ff">if</span>(value == <span style="color: #0000ff">null</span><span style="color: #000000">){</br>
            rwl.readLock().unlock();</br>
            rwl.writeLock().lock();</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">if</span>(value == <span style="color: #0000ff">null</span><span style="color: #000000">){  //防止后边线程加载数据,使用双端检测机制</br>
                    value </span>= "xxx"; <span style="color: #008000">//</span><span style="color: #008000">queryDB</span></br>

cache.put(key, value);
}
}
finally{
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
}
catch (Exception e) {
}
finally{
rwl.readLock().unlock();
}
return value;
}

}

Java多线程与并发库高级应用-工具类介绍

ReadWriteLock javaAPI中有缓存的代码:

class CachedData {
   Object data;
   volatile boolean cacheValid;
   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
// Recheck state because another thread might have acquired
// write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
rwl.writeLock().unlock(); // Unlock write, still hold read
}

 use(data);</br>
 rwl.readLock().unlock();</br>

}
}

3、Condition 实现线程通信

传统的线程通信方式

Java多线程与并发库高级应用-工具类介绍
/*
 * 传统线程通信
 * 主线程和子线程分别打印 100次 和 10次,循环50次
 */
public class TraditionalThreadCommunication2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Buiness buiness = <span style="color: #0000ff">new</span><span style="color: #000000"> Buiness();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
                buiness.sub(i);</br>
            }</br>
        }</br>
    }).start();</br></br>
    
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
        buiness.main(i);</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Buiness{</br>
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">boolean</span> isShouldSub = <span style="color: #0000ff">false</span>;  <span style="color: #008000">//</span><span style="color: #008000">主线程先打印</span></br>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span> j){ <span style="color: #008000">//</span><span style="color: #008000">进行同步,防止在打印时被其他线程干扰</span></br>
        <span style="color: #0000ff">while</span>(isShouldSub){  <span style="color: #008000">//</span><span style="color: #008000">这里使用while 防止假唤醒</span></br>
            <span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">this</span>.wait();  <span style="color: #008000">//</span><span style="color: #008000">wait() 和 notify() 必须出现在synchronized同步中</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=100;i++<span style="color: #000000">){</br>
            System.out.println(</span>"main thread print "+ i + " loop of " +<span style="color: #000000"> j);</br>
        }</br>
        isShouldSub </span>= <span style="color: #0000ff">true</span><span style="color: #000000">;</br>
        </span><span style="color: #0000ff">this</span><span style="color: #000000">.notify();</br>
    }</br>
    </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">synchronized</span> <span style="color: #0000ff">void</span> sub(<span style="color: #0000ff">int</span><span style="color: #000000"> j){</br>
        </span><span style="color: #0000ff">while</span>(!<span style="color: #000000">isShouldSub){</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                </span><span style="color: #0000ff">this</span><span style="color: #000000">.wait();</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1 ; i&lt;=10;i++<span style="color: #000000">){</br>
            System.out.println(</span>"sub thread print "+ i + " loop of " +<span style="color: #000000"> j);</br>
        }</br>
        isShouldSub </span>= <span style="color: #0000ff">false</span><span style="color: #000000">;</br>
        </span><span style="color: #0000ff">this</span><span style="color: #000000">.notify();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

将上述程序改写为使用Condition

Java多线程与并发库高级应用-工具类介绍
/*
 * 传统线程通信
 * 主线程和子线程分别打印 100次 和 10次,循环50次
 * 改写成使用 Condition 的方式
 */
public class TraditionalThreadCommunication2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Buiness buiness = <span style="color: #0000ff">new</span><span style="color: #000000"> Buiness();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
                buiness.sub(i);</br>
            }</br>
        }</br>
    }).start();</br></br>
    
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=50;i++<span style="color: #000000">){</br>
        buiness.main(i);</br>
    }</br>
}</br></br>

</span><span style="color: #008000">/**</span><span style="color: #008000"></br>
 * 将程序改写为使用Lock&amp;Condition的方式进行 同步和通信</br>
 * </span><span style="color: #808080">@author</span><span style="color: #008000"> Administrator</br>
 *</br>
 </span><span style="color: #008000">*/</span></br></br>
<span style="color: #0000ff">static</span> <span style="color: #0000ff">class</span><span style="color: #000000"> Buiness{
    Lock lock </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantLock();</br>
    Condition condition </span>=<span style="color: #000000"> lock.newCondition();</br>
    </span><span style="color: #0000ff">private</span> <span style="color: #0000ff">boolean</span> isShouldSub = <span style="color: #0000ff">false</span>;  <span style="color: #008000">//</span><span style="color: #008000">主线程先打印</span>
    <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span> j){ <span style="color: #008000">//</span><span style="color: #008000">进行同步,防止在打印时被其他线程干扰</span>

lock.lock();
try {
while(isShouldSub){ //这里使用while 防止假唤醒
try {
condition.await();
// this.wait(); //wait() 和 notify() 必须出现在同步监视器内部中
} catch (Exception e) {
e.printStackTrace();
}
}
for(int i = 1;i<=100;i++){
System.out.println(
"main thread print "+ i + " loop of " + j);
}
isShouldSub
= true;
condition.signal();
// this.notify();
} finally {
lock.unlock();
}
}
public void sub(int j){
lock.lock();
try {
while(!isShouldSub){
try {
condition.await();
// this.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
for(int i = 1 ; i<=10;i++){
System.out.println(
"sub thread print "+ i + " loop of " + j);
}
isShouldSub
= false;
condition.signal();
// this.notify();
} finally{
lock.unlock();
}
}
}

}

Java多线程与并发库高级应用-工具类介绍

main thread print 1 loop of 1
main thread print 2 loop of 1
main thread print 3 loop of 1
main thread print 4 loop of 1
main thread print 5 loop of 1
main thread print 6 loop of 1
main thread print 7 loop of 1
...
main thread print 99 loop of 1
main thread print 100 loop of 1
sub thread print 1 loop of 1
sub thread print 2 loop of 1
sub thread print 3 loop of 1
sub thread print 4 loop of 1
sub thread print 5 loop of 1
sub thread print 6 loop of 1
sub thread print 7 loop of 1
sub thread print 8 loop of 1
sub thread print 9 loop of 1
sub thread print 10 loop of 1
main thread print 1 loop of 2
main thread print 2 loop of 2
main thread print 3 loop of 2
main thread print 4 loop of 2
main thread print 5 loop of 2
main thread print 6 loop of 2
main thread print 7 loop of 2
main thread print 8 loop of 2
main thread print 9 loop of 2
...
main thread print 99 loop of 2
main thread print 100 loop of 2
sub thread print 1 loop of 2
sub thread print 2 loop of 2
sub thread print 3 loop of 2
sub thread print 4 loop of 2
sub thread print 5 loop of 2
sub thread print 6 loop of 2
sub thread print 7 loop of 2
sub thread print 8 loop of 2
sub thread print 9 loop of 2
sub thread print 10 loop of 2
main thread print 1 loop of 3
main thread print 2 loop of 3
main thread print 3 loop of 3

...

使用Condition比传统的好处

可以实现多路Condition ,在javaAPI中有

class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition(); 
   final Condition notEmpty = lock.newCondition(); 

final Object[] items = new Object[100];
int putptr, takeptr, count;

public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}

public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}

使用多路Condition,可以扩展上述的一个例子,老大打印完 -> 老二   老二-> 老三  老三-> 老大  老大-> 老二...

Java多线程与并发库高级应用-工具类介绍
/**
 * 第一个线程循环100次,第二个线程循环10次,第三个线程循环20次,如此循环50次,请写出程序 这里使用Condition
 * 
 * @author Administrator
 * 
 */
public class ThreeConditionCommunication {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Business2 business = <span style="color: #0000ff">new</span><span style="color: #000000"> Business2();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
                business.sub2(i);</br>
            }</br>
        }</br>
    }).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
                business.sub3(i);</br>
            }</br>
        }</br>
    }).start();</br></br>

    </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 1; i &lt;= 50; i++<span style="color: #000000">) {</br>
        business.main(i);</br>
    }</br>
}</br></br>

}

class Business2 {
Lock lock
= new ReentrantLock();
Condition condition1
= lock.newCondition();
Condition condition2
= lock.newCondition();
Condition condition3
= lock.newCondition();
private int shoudeSub = 1;
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sub2(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 2) { <span style="color: #008000">//</span><span style="color: #008000"> 这里也可以用 if ,用while比较好一些 As in the one argument</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> version, interrupts and spurious wakeups are</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> possible, and this method should always be</br>
                                </span><span style="color: #008000">//</span><span style="color: #008000"> used in a loop</span></br>
            <span style="color: #0000ff">try</span> { <span style="color: #008000">//</span><span style="color: #008000"> 防止线程有可能被假唤醒 (while放在这里提现了水准)</span></br>
                condition2.await();  <span style="color: #008000">//</span><span style="color: #008000">等待</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 100; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"sub2 thread sequence of " + j + ", loop of " +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 3<span style="color: #000000">;</br>
        condition3.signal();</span><span style="color: #008000">//</span><span style="color: #008000">唤醒</span></br>
    } <span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> sub3(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 3) { <span style="color: #008000">//</span><span style="color: #008000"> 这里也可以用 if ,用while比较好一些 As in the one argument</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> version, interrupts and spurious wakeups are</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> possible, and this method should always be</br>
            </span><span style="color: #008000">//</span><span style="color: #008000"> used in a loop</span></br>
            <span style="color: #0000ff">try</span> { <span style="color: #008000">//</span><span style="color: #008000"> 防止线程有可能被假唤醒 (while放在这里提现了水准)</span></br>
                condition3.await();  <span style="color: #008000">//</span><span style="color: #008000">等待</span></br>
            } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 20; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"sub3 thread sequence of " + j + ", loop of " +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 1<span style="color: #000000">;</br>
        condition1.signal();</span><span style="color: #008000">//</span><span style="color: #008000">唤醒</span></br>
    } <span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> main(<span style="color: #0000ff">int</span><span style="color: #000000"> i) {</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        </span><span style="color: #0000ff">while</span> (shoudeSub != 1<span style="color: #000000">) {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                condition1.await();</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                e.printStackTrace();</br>
            }</br>
        }</br>
        </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> j = 1; j &lt;= 10; j++<span style="color: #000000">) {</br>
            System.out.println(</span>"main thread sequence of " + j + ", loop of "</br>
                    +<span style="color: #000000"> i);</br>
        }</br>
        shoudeSub </span>= 2<span style="color: #000000">;</br>
        condition2.signal();</br>
    } </span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #008000">/**</span><span style="color: #008000"></br>
 * </br>
 * synchronized (obj) { 这里的obj与obj.wait必须相同,否则会抛异常 while (&lt;condition does</br>
 * not hold&gt;) obj.wait(); ... // Perform action appropriate to condition }</br>
 </span><span style="color: #008000">*/</span><span style="color: #000000"></br>

}

Java多线程与并发库高级应用-工具类介绍

Condition的一个例子:

 编写一个程序,开启3个线程 ,这三个线程的ID分别为 A,B, C,每个线程将自己的ID 在屏幕上打印10遍,要求输出的结果必须按顺序显示。

如:ABCABCABC.....依次递归

这里实现了一个比题目稍微难得例子,A 打印10次,B打印20次 ,C打印5次依次递归20次。

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestAlternative {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    </span><span style="color: #0000ff">final</span> Alternative alternative = <span style="color: #0000ff">new</span><span style="color: #000000"> Alternative();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopA(i);</br>
            }</br>
        }</br>
    },</span>"A"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopB(i);</br>
            }</br>
        }</br>
    },</span>"B"<span style="color: #000000">).start();</br>
    </span><span style="color: #0000ff">new</span> Thread(<span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
                alternative.loopC(i);</br>
                System.out.println(</span>"-----------------"<span style="color: #000000">);</br>
            }</br>
        }</br>
    },</span>"C"<span style="color: #000000">).start();</br>
    </br>
}</br>
}
class Alternative{
</span><span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> number = 1<span style="color: #000000">;</br>
</span><span style="color: #0000ff">private</span> Lock lock = <span style="color: #0000ff">new</span><span style="color: #000000"> ReentrantLock();</br>
</span><span style="color: #0000ff">private</span> Condition condition1 =<span style="color: #000000"> lock.newCondition();</br>
</span><span style="color: #0000ff">private</span> Condition condition2 =<span style="color: #000000"> lock.newCondition();</br>
</span><span style="color: #0000ff">private</span> Condition condition3 =<span style="color: #000000"> lock.newCondition();</br></br>

</span><span style="color: #0000ff">void</span> loopA(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 1<span style="color: #000000">){</br>
            condition1.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=10;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 2<span style="color: #000000">;</br>
        condition2.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000"> {</br>
        lock.unlock();</br>
    }</br>
}</br></br>

</span><span style="color: #0000ff">void</span> loopB(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 2<span style="color: #000000">){</br>
            condition2.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=20;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 3<span style="color: #000000">;</br>
        condition3.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
        </br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>
</span><span style="color: #0000ff">void</span> loopC(<span style="color: #0000ff">int</span><span style="color: #000000"> outerLoop){</br>
    lock.lock();</br>
    </span><span style="color: #0000ff">try</span><span style="color: #000000">{</br>
        </span><span style="color: #0000ff">while</span>(number != 3<span style="color: #000000">){</br>
            condition3.await();</br>
        }</br>
        </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 1;i&lt;=5;i++<span style="color: #000000">){</br>
            System.out.println(Thread.currentThread().getName() </span>+ "	" + i + "	" +<span style="color: #000000"> outerLoop);</br>
        }</br>
        number </span>= 1<span style="color: #000000">;</br>
        condition1.signal();</br>
    }</span><span style="color: #0000ff">catch</span><span style="color: #000000">(Exception e){</br>
        </br>
    }</span><span style="color: #0000ff">finally</span><span style="color: #000000">{</br>
        lock.unlock();</br>
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

java5的Semaphere同步工具

  Semaphore实现信号灯

  Semaphore可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。

  假设一个文件同时可以被3个人访问,来了5个人,同时只有3个访问。3个中任何一个出来后,等待的就可以进去了。

Java多线程与并发库高级应用-工具类介绍
public class SemaphoreTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>
    ExecutorService service </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span>  Semaphore sp = <span style="color: #0000ff">new</span> Semaphore(3<span style="color: #000000">);  //还有一个构造方法,<code><strong><a>Semaphore</a></strong>(int permits, boolean fair)</code>  fair参数为true表示谁先来谁先进,一种公平的原则 </br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i=0;i&lt;10;i++<span style="color: #000000">){</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable(){</br>
                </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run(){</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    sp.acquire();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e1) {</br>
                    e1.printStackTrace();</br>
                }</br>
                System.out.println(</span>"线程" + Thread.currentThread().getName() + </br>
                        "进入,当前已有" + (3-sp.availablePermits()) + "个并发"<span style="color: #000000">);</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>)(Math.random()*10000<span style="color: #000000">));</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
                    e.printStackTrace();</br>
                }</br>
                System.out.println(</span>"线程" + Thread.currentThread().getName() + </br>
                        "即将离开"<span style="color: #000000">);                    </br>
                sp.release();
                </span><span style="color: #008000">//</span><span style="color: #008000">下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元</span></br>
                System.out.println("线程" + Thread.currentThread().getName() + 
                        "已离开,当前已有" + (3-sp.availablePermits()) + "个并发"<span style="color: #000000">);                    </br>
            }</br>
        };</br>
        service.execute(runnable);           </br> 
    }</br>
}</br>

}

Java多线程与并发库高级应用-工具类介绍

单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了 "锁",再由另外一个线程释放"锁",这可应用于死锁恢复的一些场合。

java5 的CyclicBarrier同步工具

Java多线程与并发库高级应用-工具类介绍
/**
 * 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面,
 * 这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,
 * 再同时出发到公园游玩,在指定地点集合后再同时开始就餐,…。
 * @author Administrator
 *
 */
public class CyclicBarrierTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService threadPool </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> CyclicBarrier cb = <span style="color: #0000ff">new</span> CyclicBarrier(3<span style="color: #000000">);</br>
    </span><span style="color: #0000ff">for</span> (<span style="color: #0000ff">int</span> i = 0; i &lt; 3; i++<span style="color: #000000">) {</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br>
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                                    </span>+ "即将到达集合点1,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br></br>
                    
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                            </span>+ "即将到达集合点2,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br></br>
                    
                    Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000"> Thread.currentThread().getName()</br>
                            </span>+ "即将到达集合点3,当前已有 "+(cb.getNumberWaiting()+1) +"个已经到达,"+(cb.getNumberWaiting() == 2?"都到齐了,继续走啊":"正在等待"<span style="color: #000000">));</br>
                    cb.await();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                    </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
};
threadPool.execute(runnable);
}
threadPool.shutdown();
}

}

Java多线程与并发库高级应用-工具类介绍

java5的CountDownLatch同步工具

  CountDownLatch : 闭锁,在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才继续执行

  CountDownLatch应用1:比如要统计5个线程并发的运行时间,即线程的开始时间与最后一个线程的运行结束时间的间隔时间。

  

Java多线程与并发库高级应用-工具类介绍
package com.java.juc;

import java.util.concurrent.CountDownLatch;

public class TestCountDownLatch2 {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br></br>

    CountDownLatch latch </span>= <span style="color: #0000ff">new</span> CountDownLatch(5<span style="color: #000000">);</br>
    LatchDemo2 ld </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> LatchDemo2(latch);</br></br>
    
    </span><span style="color: #0000ff">long</span> start =<span style="color: #000000"> System.currentTimeMillis();</br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;5;i++<span style="color: #000000">){</br>
        </span><span style="color: #0000ff">new</span><span style="color: #000000"> Thread(ld).start();</br></br>
    }
    </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
        latch.await();   </span><span style="color: #008000">//</span><span style="color: #008000">先执行完成的线程需要等待还没有执行完的线程</span></br>
    } <span style="color: #0000ff">catch</span><span style="color: #000000"> (InterruptedException e) {</br>
        e.printStackTrace();</br>
    }</br></br>
    
    </span><span style="color: #0000ff">long</span> end  =<span style="color: #000000"> System.currentTimeMillis();</br>
    System.out.println(</span>"cost: "+ (end -<span style="color: #000000"> start));</br>
}</br>
}

class LatchDemo2 implements Runnable{
private CountDownLatch latch;
</span><span style="color: #0000ff">public</span><span style="color: #000000"> LatchDemo2(CountDownLatch latch) {</br>
    </span><span style="color: #0000ff">this</span>.latch =<span style="color: #000000"> latch;</br>
}</br></br>

@Override</br>
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
try { synchronized(this){ for(int i = 0;i<50000;i++){ //找出50000以内的所有偶数 if(i % 2 == 0){ System.out.println(i); } } } } finally{ latch.countDown(); //为了让这一句一定执行可以放在finally中 } } }
Java多线程与并发库高级应用-工具类介绍

  还可以应用于计算所有种类商品的平均销售总和,平均销售时间等,如果使用单线程计算效率非常低,相当于是串行计算。可以使用并行计算,按照商品种类进行区分并行的计算。可以将最终的每个线程的计算结果在进行汇总,可以得出最终的的总的销售数据,这就可以使用CountDownLatch进行操作,可以大幅度提高效率。(京东)

Java多线程与并发库高级应用-工具类介绍

应用:运动员跑步比赛,得到最终的排名需要在所有运动员都完成之后,公布最终的结果。

Java多线程与并发库高级应用-工具类介绍
/**
 * 犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减一,
 * 当计数器到达0时,则所有等待者或单个等待者开始执行。
 * 可以实现一个人(也可以是多个人)等待其他所有人都来通知他,可以实现一个人通知多个人的效果,
 * 类似裁判一声口令,运动员同时开始奔跑,或者所有运动员都跑到
 * 终点后裁判才可以公布结果。还可以实现一个计划需要多个领导都签字后
 * 才能继续向下实施的情况
 * @author Administrator
 *
 */
public class CountDownLetchTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService executorService </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> CountDownLatch cdOrder = <span style="color: #0000ff">new</span> CountDownLatch(1); <span style="color: #008000">//</span><span style="color: #008000">计数器初始值 1</span></br>
    <span style="color: #0000ff">final</span> CountDownLatch cdAnswer = <span style="color: #0000ff">new</span> CountDownLatch(3<span style="color: #000000">);</br>
    </span><span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i = 0;i&lt;3;i++<span style="color: #000000">){</br>
        Runnable runnable </span>= <span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br></br>
            
            @Override
            </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
                </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"正准备接受命令"<span style="color: #000000">);</br>
                    cdOrder.await();</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"已接受命令"<span style="color: #000000">);</br>
                    Thread.sleep((</span><span style="color: #0000ff">long</span>)(Math.random()*10000<span style="color: #000000">));</br>
                    System.out.println(</span>"线程"+<span style="color: #000000">Thread.currentThread().getName()</br>
                            </span>+"回应命令处理结果"<span style="color: #000000">);</br>
                    cdAnswer.countDown();</br>
                } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                    </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
};
executorService.execute(runnable);
}
try {
Thread.sleep((
long)(Math.random()*10000));
System.out.println(
"线程"+Thread.currentThread().getName()
+"即将发布命令");
cdOrder.countDown();
//计数器数值减 1
System.out.println("线程"+Thread.currentThread().getName()
+"已发送命令,正在等待结果");
cdAnswer.await();
System.out.println(
"线程"+Thread.currentThread().getName()
+"已收到所有响应结果");
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
executorService.shutdown();
}
}

Java多线程与并发库高级应用-工具类介绍

 java 中CycliBarriar 和 CountDownLatch 有什么区别?

  这两个的区别是CyclicBarrier 可以重复使用已经通过的障碍,而 CountdownLatch 不能重复使用。

java5的Exchanger同步工具

Java多线程与并发库高级应用-工具类介绍
/**
 * 用于实现两个人之间的数据交换,每个人在完成一定的事物后想与对方交换数据,第一个先拿出数据的人将
 * 一直等待第二个人拿着数据到来时,才能彼此交换数据。
 * @author Administrator
 *
 */
public class ExchangerTest {
</span><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {</br>
    ExecutorService executorService </span>=<span style="color: #000000"> Executors.newCachedThreadPool();</br>
    </span><span style="color: #0000ff">final</span> Exchanger exchanger = <span style="color: #0000ff">new</span><span style="color: #000000"> Exchanger();</br>
    executorService.execute(</span><span style="color: #0000ff">new</span><span style="color: #000000"> Runnable() {</br></br>

        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                String data1 </span>= "aaa"<span style="color: #000000">;</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "正在把数据" + data1 + "换出去"<span style="color: #000000">);</br>
                Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                String data2 </span>=<span style="color: #000000"> (String) exchanger.exchange(data1);</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "换回的数据为 " +<span style="color: #000000"> data2);</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
});
executorService.execute(
new Runnable() {

        @Override</br>
        </span><span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> run() {</br>
            </span><span style="color: #0000ff">try</span><span style="color: #000000"> {</br>
                String data1 </span>= "bbb"<span style="color: #000000">;</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "正在把数据" + data1 + "换出去"<span style="color: #000000">);</br>
                Thread.sleep((</span><span style="color: #0000ff">long</span>) (Math.random() * 10000<span style="color: #000000">));</br>
                String data2 </span>=<span style="color: #000000"> (String) exchanger.exchange(data1);</br>
                System.out.println(</span>"线程" +<span style="color: #000000"> Thread.currentThread().getName()</br>
                        </span>+ "换回的数据为 " +<span style="color: #000000"> data2);</br>
            } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {</br>
                </span><span style="color: #008000">//</span><span style="color: #008000"> TODO: handle exception</span></br>

}
}
});
}

}

Java多线程与并发库高级应用-工具类介绍

打印结果为:

线程 pool-1-thread-1正把数据 aaa 换出去

线程 pool-1-thread-2正把数据 bbb 换出去

线程 pool-1-thread-2换回的数据为 aaa

线程 pool-1-thread-1换回的数据为 bbb