同步工具类(闭锁,信号量,栅栏,FutureTask)

来源:互联网 发布:淘宝退货用空包判刑吗 编辑:程序博客网 时间:2024/05/19 03:42

闭锁:可以延迟线程的进度直到其到达终止状态。

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<T> {
private final Set<T> set;
private final Semaphore sema;

public SemaphoreTest(int bound){
this.set = Collections.synchronizedSet(new HashSet<T>());
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<Integer> test = new SemaphoreTest<Integer>(permits);
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<workers.length;i++){
new Thread(workers[i]).start();
}
}

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<ProductInfo> future =
        new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
            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 { }

0 0
原创粉丝点击