昨晚闲来翻了一会Java ConcurrentCy in Practise,
进一步明确了java 一些 Synchronizers的用法,在此简单记录一下
昨日随手写的demo代码。只是为了加深印象,所以不怎么讲究,如有看官路过请不要挑剔:
import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class NightDinner { private Semaphore sem=new Semaphore(3); private CountDownLatch startLatch=new CountDownLatch(1); private CountDownLatch latch=new CountDownLatch(4); private CyclicBarrier barrier=new CyclicBarrier(2,new Runnable(){ public void run() { System.out.println("barrier tripped"); }}); private ReentrantLock lock=new ReentrantLock(); private Condition condition=lock.newCondition(); public static void main(String[] args) { NightDinner nd=new NightDinner(); nd.testLatch(); nd.testBarrier(); nd.testLock(); nd.testSemaphore(); } public void testLatch(){ for(int i=0;i<4;i++){ new Thread(new AThread()).start(); } startLatch.countDown(); System.out.println("latch begin"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("latch zero reached"); } public void testBarrier(){ for(int i=0;i<2;i++){ new Thread(new BThread()).start(); } } public void testLock(){ for(int i=0;i<3;i++) new Thread(new CThread()).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } lock.lock(); //condition.signal(); condition.signalAll(); //要显式地释放掉lock的锁 lock.unlock(); } public void testSemaphore(){ for(int i=0;i<4;i++) new Thread(new DThread()).start(); } public class AThread implements Runnable{ public void run() { try { startLatch.await(); } catch (InterruptedException e) { } latch.countDown(); System.out.println("latch down1"); } } public class BThread implements Runnable{ public void run() { try { System.out.println("barrier begints to await"); barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } public class CThread implements Runnable{ public void run() { lock.lock(); try { System.out.println("lock got.conditon begins to wait"); //condition的wait方法将release当前线程持有的condtion相关的lock的锁,然后等待被唤醒 condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally{ System.out.println("conditon signaled"); lock.unlock(); } } } public class DThread implements Runnable{ public void run() { boolean suc=sem.tryAcquire(); System.out.println("sem result:"+suc); } } }
总结一下,就是:
CountdownLatch:
一个主人线程一直await,知道所有客人线程都countdown并且latch的值为0,那么
主人认为时机已成熟,开饭。
CyclicBarrier:
一桌有10个位子,人不满不能开席(定义cyclicbarrier的时候可选的runnable行为)。于是,来了一个(await),又来了一个...第10个来了,barrier发现时机已成熟,开饭。
Semapore:
一桌有10个位子。来了一个(acquire)..第10个来了....第11个来了....哈哈,没有位子了,站着吧
ReentrantLock:
这个官方文档可能读起来不是很顺畅,还是通过代码明白得更深入一些。
一个lock可以有多个Condtion。每个Condtion都有一个管理的lock。
Conditon可以await(释放掉关联的Lock的锁,等待notif),也可以notify(通知其他线程处于condtion await 状态的线程可以做好继续获取lock的锁的准备了。notify之后要显式地释放掉lock锁).