Barrier是一种堵塞,相当于上锁(synchronized),CyclicBarrier是用来让线程之间进行相互等待,CyclicBarrier在一些数目固定的多线程之间在某些地方需要等待其它线程的时候是非常有用的,它们之所以被叫做Cyclic,是因为它们在其它堵塞了的线程被释放之后还可以再使用。
下面是它提供给外部的一些方法:
1、 public CyclicBarrier(int parties, Runnable barrierAction)
构造子,参数有两个:分配的线程数目和所有线程都到达堵塞点的时候需要运行的任务。
2、 public CyclicBarrier(int parties)
构造子,参数为将要合作运行的线程数目。
3、 public int getParties()
取得将要合作运行的线程的数目。
4、 public int await() throws InterruptedException, BrokenBarrierException
等待其它合作伙伴的到来,如果当前线程不是最后一个到达的线程,那么它会堵塞,沉睡,直到最后一个线程的到来,然后继续运行下去,在继续运行之前会先运行构造子里面传入的任务,如果出现了等待线程被破坏,或者其它的一些意外情况,那么将会抛出异常。
5、 public int await(long timeout, TimeUnit unit)
和上面的public int await() throws InterruptedException, rokenBarrierException 一样,只是设置了一个堵塞的最长时间。如果超时了的话就
抛出一个异常。
6、 public boolean isBroken()
判断在堵塞点设置的障碍是否出于正常状态。
7、 public void reset()
将堵塞点的状态重新初始化,如果发现有线程还在等待其它线程的到来,就抛出一个异常。
8、 public int getNumberWaiting()
取得等待线程的数量。
eg:
/*
* Created on 2004-8-25
*/
package test1;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author <a mailto:href=%22mailto:Azure_2003@126.com%22>Azure</a>
*
*/
public class Myte {
public static int number = 1;
public final static int MAX = 5;
public static CyclicBarrier barrier;
public static Myte myte;
public static void main(String[] args) {
myte = new Myte();
barrier = new CyclicBarrier(1, myte.new Worker());
Manager manager = myte.new Manager();
try {
myte.getItem();
manager.run();
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("game over!");
}
public void getItem() throws InterruptedException {
System.out.println(barrier.getParties());
System.out.println(barrier.isBroken());
System.out.println(barrier.getNumberWaiting());
}
class Manager implements Runnable {
public void run() {
System.out.println("run thread Manager");
}
}
class Worker implements Runnable {
public void run() {
System.out.println("run thread Worker");
}
}
}
结果打印出来为:
1
false
0
run thread Manager
run thread Worker
game over!
十二、Exchanger
Exchanger使用可重入锁ReentrantLock来实现的,用来帮助两个线程之间进行数据交换。
它提供给我们的方法只有两个:
1、 public V exchange(V x) throws InterruptedException
x是需要交换的对象。
2、 public V exchange(V x, long timeout, TimeUnit unit)
在有限的时间里交换x对象,如果超时,会抛出一个异常。
eg:
这是Doug Lea的例子(DataBuffer有待实现):
class FillAndEmpty {
Exchanger exchanger = new Exchanger();
DataBuffer initialEmptyBuffer=new DataBuffer();
DataBuffer initialFullBuffer=new DataBuffer();
class FillingLoop
implements Runnable {
public void run() {
DataBuffer currentBuffer = initialEmptyBuffer;
try {
while (currentBuffer != null) {
addToBuffer(currentBuffer);
if (currentBuffer.full())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) {
}
}
}
class EmptyingLoop implements Runnable {
public void run() {
DataBuffer currentBuffer = initialFullBuffer;
try {
while (currentBuffer != null) {
takeFromBuffer(currentBuffer);
if (currentBuffer.empty())
currentBuffer = exchanger.exchange(currentBuffer);
}
} catch (InterruptedException ex) {
}
}
}
void start() {
new Thread(new FillingLoop()).start();
new Thread(new EmptyingLoop()).start();
}
}