闭锁:可以延迟线程的进度直到其到达终止状态。
public class LatchDemo {
public static 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 ignored) {
}
}
};
t.start();
}
long start = System.nanoTime();
startGate.countDown();//表示有一个事件发生
endGate.await();//等待计数器清零,表示所有需要等待的事件都已经发生
long end = System.nanoTime();
return end - start;
}
public static void main(String[] args) throws InterruptedException{
System.out.println(timeTasks(5, new Demo()));
}
}
class Demo implements Runnable{
public void run() {
System.out.println("hello");
}
}
结果:
hello
hello
hello
hello
1027743
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
信号量:用来控制同时访问某个特定的操作数量,或者同时执行某个指定操作的数量。另外,信号量还可以用来实现某种资源池,或者对容器加边界。
public class SemaphoreTest
private final Set
private final Semaphore sema;
public SemaphoreTest(int bound){
this.set = Collections.synchronizedSet(new HashSet
this.sema = new Semaphore(bound);
}
public boolean add(T o) throws InterruptedException{
sema.acquire();
boolean wasAdded = false;
try{
wasAdded = set.add(o);
System.out.println(wasAdded);
return wasAdded;
}finally{
if(!wasAdded){
sema.release();
}
}
}
public boolean remove(T o){
boolean wasRemoved = set.remove(o);
if(wasRemoved){
sema.release();
}
return wasRemoved;
}
public static void main(String[] args) throws InterruptedException{
int permits = 3;//允许多少个,true有多少个
int elements = permits + 1;
SemaphoreTest
for(int i = 0;i < elements; i++){
test.add(i);
}
}
}
结果:输出三个true(true的个数和permits参数一致)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
栅栏:类似于闭锁,它能阻塞一组线程知道某个事件发生。并能重复进行计算多次,而闭锁不能实现重复计算。
public class CyclicBarrierTest {
private final CyclicBarrier barrier;
private final Worker[] workers;
public CyclicBarrierTest(){
int count = Runtime.getRuntime().availableProcessors();
this.barrier = new CyclicBarrier(count,
new Runnable(){
@Override
public void run() {
System.out.println("所有线程均到达栅栏位置,开始下一轮计算");
}
});
this.workers = new Worker[count];
for(int i = 0; i< count;i++){
workers[i] = new Worker(i);
}
}
private class Worker implements Runnable{
int i;
public Worker(int i){
this.i = i;
}
@Override
public void run() {
for(int index = 1; index < 3;index++){
System.out.println("线程" + i + "第" + index + "次到达栅栏位置,等待其他线程到达");
try {
//注意是await,而不是wait
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
return;
} catch (BrokenBarrierException e) {
e.printStackTrace();
return;
}
}
}
}
public void start(){
for(int i=0;i
}
}
public static void main(String[] args){
new CyclicBarrierTest().start();
}
}
结果:
线程1第1次到达栅栏位置,等待其他线程到达
线程3第1次到达栅栏位置,等待其他线程到达
线程2第1次到达栅栏位置,等待其他线程到达
线程0第1次到达栅栏位置,等待其他线程到达
所有线程均到达栅栏位置,开始下一轮计算
线程3第2次到达栅栏位置,等待其他线程到达
线程2第2次到达栅栏位置,等待其他线程到达
线程1第2次到达栅栏位置,等待其他线程到达
线程0第2次到达栅栏位置,等待其他线程到达
所有线程均到达栅栏位置,开始下一轮计算
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
FutureTask:通过将FutureTask封装进线程,通过启动线程提前启动计算,若数据已经加载,那么将返回这些数据,否则将等待加载完成后再返回。
public class Preloader {
ProductInfo loadProductInfo() throws DataLoadException {
return null;
}
private final FutureTask
new FutureTask
public ProductInfo call() throws DataLoadException {
return loadProductInfo();
}
});
private final Thread thread = new Thread(future);
public void start() { thread.start(); }
public ProductInfo get()
throws DataLoadException, InterruptedException {
try {
return future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof DataLoadException)
throw (DataLoadException) cause;
else
throw LaunderThrowable.launderThrowable(cause);
}
}
interface ProductInfo {
}
}
class DataLoadException extends Exception { }