同步工具类包括信号量(Semaphore)、栅栏(barrier)、闭锁(CountDownLatch)
闭锁(CountDownLatch)
public class RunMain {
public long timeTasks(int nThreads, final Runnable task) throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread t = new Thread() {
public void run() {
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
};
t.start();
}
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end - start;
}
}
FutrureTask
FutureTask也可以做闭锁,FutureTask表示的计算是通过Callable来实现的,相当于一种可生成结果的Runnable,并且可以处于一下3中状态
- 等待运行
- 正在运行
- 运行完成:表示计算的所有可能结束方式包括正常结束、由于取消而结束和由于异常而结束等。当FutureTask进入完成状态后,它会永远停止在这个状态上。
Future.get的行为取决于任务的状态,如果任务已经完成,那么get会立即返回结果,否则将阻塞知道完成状态,然后返回结果或者抛出异常。FutureTask将计算结果从执行计算的线程传递到获取这个结果的线程,而FutureTask的规范确保了这种传递过程能实现结果的安全发布。
public class RunMain {
private FutureTask<String> future = new FutureTask<String>(new Callable<String>() {
public String call() throws Exception {
System.err.println("数据加载中");
Thread.sleep(3000);
return "数据加载完成";
};
});
private Thread thread = new Thread(future);
public void start() {
thread.start();
}
public String get() throws InterruptedException, ExecutionException {
return future.get();
}
public static void main(String[] args) throws InterruptedException, ExecutionException{
RunMain run = new RunMain();
run.start();
System.out.println(run.get());
}
}
信号量(Semaphore)
计数信号量用来控制同时访问某个特定资源的操作数量,或者同时执行某个制定操作的数量,计数信号量还可以用来实现某种资源池或者对容器施加边界
public class RunMain<T> {
private Set<T> set;
private Semaphore sem;
public RunMain(int bound) {
set = Collections.unmodifiableSet(new HashSet<T>());
sem = new Semaphore(bound);
}
public boolean add(T t) throws InterruptedException {
sem.acquire();
boolean boo = false;
try {
boo = set.add(t);
return boo;
} finally {
if (!boo)
sem.release();
}
}
public boolean remove(T t) {
boolean boo = set.remove(t);
if (boo)
sem.release();
return boo;
}
}
栅栏(barrier)
所有线程必须同时到达栅栏的位置,才能继续执行,闭锁用于等待事件,而栅栏用于等待其他线程。
CyclicBarrier可以使一定数量的参与方反复地在栅栏位置聚集,它在并行迭代算法中非常有用。
代码摘自:http://www.cnblogs.com/dolphin0520/p/3920397.html
public class Test {
public static void main(String[] args) {
int N = 4;
CyclicBarrier barrier = new CyclicBarrier(N,new Runnable() {
@Override
public void run() {
System.out.println("当前线程"+Thread.currentThread().getName());
}
});
for(int i=0;i<N;i++)
new Writer(barrier).start();
}
static class Writer extends Thread{
private CyclicBarrier cyclicBarrier;
public Writer(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getName()+"正在写入数据...");
try {
Thread.sleep(5000); //以睡眠来模拟写入数据操作
System.out.println("线程"+Thread.currentThread().getName()+"写入数据完毕,等待其他线程写入完毕");
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
}catch(BrokenBarrierException e){
e.printStackTrace();
}
System.out.println("所有线程写入完毕,继续处理其他任务...");
}
}
}