/** * @Description: *让一些线程阻塞直到另外一些线程完成一系列操做后才被唤醒。 * <p> * CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。 * 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞), * 当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。 * <p> * 解释:6个同窗陆续离开教室后值班同窗才能够关门。 * <p> * main主线程必需要等前面6个线程完成所有工做后,本身才能开干 */ public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 1; i <= 6; i++) //6个上自习的同窗,各自离开教室的时间不一致 { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t 号同窗离开教室"); countDownLatch.countDown(); }, String.valueOf(i)).start(); } countDownLatch.await(); System.out.println(Thread.currentThread().getName() + "\t****** 班长关门走人,main线程是班长"); } }
/** * CyclicBarrier * 的字面意思是可循环(Cyclic)使用的屏障(Barrier)。它要作的事情是, * 让一组线程到达一个屏障(也能够叫同步点)时被阻塞, * 直到最后一个线程到达屏障时,屏障才会开门,全部 * 被屏障拦截的线程才会继续干活。 * 线程进入屏障经过CyclicBarrier的await()方法。 * <p> * 集齐7颗龙珠就能够召唤神龙 */ public class CyclicBarrierDemo { public static void main(String[] args) { //CyclicBarrier(int parties, Runnable barrierAction) CyclicBarrier cyclicBarrier = new CyclicBarrier( 7, () -> { System.out.println("*****集齐7颗龙珠就能够召唤神龙"); }); for (int i = 1; i <= 7; i++) { new Thread(() -> { try { System.out.println(Thread.currentThread().getName() + "\t 星龙珠被收集 "); cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { // TODO Auto-generated catch block e.printStackTrace(); } }, String.valueOf(i)).start(); } } }
忽然又想到一个知识点(跑题中。。)wait 、await、sleep、notify、signal的区别:
wait----sleepnode
public final void await() throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); int savedState = fullyRelease(node); int interruptMode = 0; while (!isOnSyncQueue(node)) { LockSupport.park(this); if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) break; } if (acquireQueued(node, savedState) && interruptMode != THROW_IE) interruptMode = REINTERRUPT; if (node.nextWaiter != null) // clean up if cancelled unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); }
先说下来源,await是ConditionObject类里面的方法,ConditionObject实现了Condition接口;而ReentrantLock里面默认有实现newCondition()方法,新建一个条件对象。该方法就是用在ReentrantLock中根据条件来设置等待。唤醒方法也是由专门的Signal()或者Signal()来执行。另外await会致使当前线程被阻塞,会放弃锁,这点和wait是同样的。并发
因为所在的超类不一样使用场景也不一样,wait通常用于Synchronized中,而await只能用于ReentrantLock锁中.
notify----signal
notify使用来唤醒使用wait的线程;而signal是用来唤醒await线程。dom
/**ui
@Description: TODO(这里用一句话描述这个类的做用)this
在信号量上咱们定义两种操做:线程
acquire(获取) 当一个线程调用acquire操做时,它要么经过成功获取信号量(信号量减1),code
要么一直等下去,直到有线程释放信号量,或超时。对象
release(释放)实际上会将信号量的值加1,而后唤醒等待的线程。接口
信号量主要用于两个目的,一个是用于多个共享资源的互斥使用,另外一个用于并发线程数的控制。
*/
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);//模拟3个停车位ip
for (int i = 1; i <= 6; i++) //模拟6部汽车 { new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "\t 抢到了车位"); TimeUnit.SECONDS.sleep(new Random().nextInt(5)); System.out.println(Thread.currentThread().getName() + "\t ----离开了车位"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } }, String.valueOf(i)).start(); }
} }