第一节 CountDownLatchhtml
(1)初识CountDownLatchjava
(2)详述CountDownLatch程序员
CountDownLatch是经过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了本身的任务后,计数器的值就会减1,当计数器值到达0时,它表示全部的线程已经完成了任务,而后在闭锁上等待的线程就能够恢复执行任务。数据库
CountDownLatch中主要方法以下:服务器
public CountDownLatch(int count),构造函数中的count(计数器)实际上就是闭锁须要等待的线程数量,这个值只能被设置一次,并且CountDownLatch没有提供任何机制去从新设置这个计数值。多线程
public void countDown(),每调用一次这个方法,在构造函数中初始化的count值就减1,通知机制是此方法来完成的。ide
public void await() throws InterruptedException,调用此方法的当前线程会一直阻塞,直到计时器的值为0。函数
(3)CountDownLatch示例ui
package com.test; import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo{ public static void main(String args[]) throws Exception{ CountDownLatch latch = new CountDownLatch(3); Worker worker1 = new Worker("Jack 程序员1",latch); Worker worker2 = new Worker("Rose 程序员2",latch); Worker worker3 = new Worker("Json 程序员3",latch); worker1.start(); worker2.start(); worker3.start(); latch.await(); System.out.println("Main thread end!"); } static class Worker extends Thread { private String workerName; private CountDownLatch latch; public Worker(String workerName,CountDownLatch latch) { this.workerName = workerName; this.latch = latch; } @Override public void run() { try { System.out.println("Worker:"+workerName +" is begin."); Thread.sleep(1000L); System.out.println("Worker:"+workerName +" is end."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }//模仿干活; latch.countDown(); } } }
上述程序运行结果以下:this
Worker:Rose 程序员2 is begin.
Worker:Json 程序员3 is begin.
Worker:Jack 程序员1 is begin.
Worker:Jack 程序员1 is end.
Worker:Json 程序员3 is end.
Worker:Rose 程序员2 is end.
Main thread end!
从结果上能够看出,MainThread执行到latch.await();处会阻塞在该处,直到三个线程均完成的时候MainThread才会继续往下执行
(4)参考资料
本小节只是简单描述了CountDownLatch的使用方式等,欲了解其实现机制,能够查看下面的几篇文章
A、http://blog.itpub.net/30024515/viewspace-1432825/
B、http://www.tuicool.com/articles/mQnAfq
第二节 CyclicBarrier
(1)初识CyclicBarrier
(2)CyclicBarrier示例
应用场景:在某种需求中,好比一个大型的任务,经常须要分配不少子任务去执行,只有当全部子任务都执行完成时候,才能执行主任务,这时候就能够选择CyclicBarrier了。
示例:
package com.test; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class CyclicBarrierDemo{ public static void main(String args[]) throws Exception{ CyclicBarrier barrier = new CyclicBarrier(3,new TotalTask()); BillTask worker1 = new BillTask("111",barrier); BillTask worker2 = new BillTask("222",barrier); BillTask worker3 = new BillTask("333",barrier); worker1.start(); worker2.start(); worker3.start(); System.out.println("Main thread end!"); } static class TotalTask extends Thread { public void run() { System.out.println("全部子任务都执行完了,就开始执行主任务了。"); } } static class BillTask extends Thread { private String billName; private CyclicBarrier barrier; public BillTask(String workerName,CyclicBarrier barrier) { this.billName = workerName; this.barrier = barrier; } @Override public void run() { try { System.out.println("市区:"+billName +"运算开始:"); Thread.sleep(1000L);//模仿第一次运算; System.out.println("市区:"+billName +"运算完成,等待中..."); barrier.await();//假设一次运算不完,第二次要依赖第一次的运算结果。都到达这个节点以后后面才会继续执行; System.out.println("所有都结束,市区"+billName +"才开始后面的工做。"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }
上述程序运行结果以下:
市区:111运算开始:
市区:333运算开始:
Main thread end! 市区:222运算开始: 市区:333运算完成,等待中... 市区:222运算完成,等待中... 市区:111运算完成,等待中... 全部子任务都执行完了,就开始执行主任务了。//这句话是最后到达wait()方法的那个线程执行的 所有都结束,市区111才开始后面的工做。 所有都结束,市区222才开始后面的工做。 所有都结束,市区333才开始后面的工做。
解说:在这个示例中,构造CyclicBarrier时,传入了内部类TotalTask(TotalTask继承了Thread,是Runnable的实现)的实例对象,其意义在于:当全部的线程都执行到wait()方法时,它们会一块儿返回继续本身的工做,可是最后一个到达wait()方法的线程会执行TotalTask的run()方法;若是在构造构造CyclicBarrier时没有传入Runnable的实现对象做为构造参数,则当全部的线程都执行到wait()方法时会直接一块儿返回继续本身的工做。
(3)CyclicBarrier与CountDownLatch的区别
A、CountDownLatch的做用是容许1或N个线程等待其余线程完成执行;而CyclicBarrier则是容许N个线程相互等待;
B、CountDownLatch的计数器没法被重置;而CyclicBarrier的计数器能够被重置后使用,所以它被称为是循环的barrier。
第三节 Semaphore
(1)初识Semaphore
Java中的Semaphore用于在线程间传递信号,从概念上讲,信号量维护了一个许可集合,Semaphore只对可用的许可进行计数,并采起相应的行动。信号量经常用于多线程的代码中,好比数据库链接池。
(2)Semaphore示例
场景:假设一个服务器资源有限,任意某一时刻只容许3我的同时进行访问,这时一共来了10我的
package com.test; import java.util.concurrent.Semaphore; public class SemaphoreDemo{ public static void main(String args[]) throws Exception{ final Semaphore semaphore = new Semaphore(3);//一次只运行3我的进行访问 for(int i=0;i<10;i++) { final int no = i; Runnable thread = new Runnable() { public void run (){ try { System.out.println("用户"+no+"链接上了:"); Thread.sleep(300L); semaphore.acquire();//获取接下去执行的许可 System.out.println("用户"+no+"开始访问后台程序..."); Thread.sleep(1000L);//模仿用户访问服务过程 semaphore.release();//释放容许下一个线程访问进入后台 System.out.println("用户"+no+"访问结束。"); } catch (InterruptedException e) { e.printStackTrace(); } } }; new Thread(thread).start(); } System.out.println("Main thread end!"); } }
上述代码运行结果以下:
用户1链接上了: 用户3链接上了: 用户4链接上了: 用户2链接上了: 用户0链接上了: 用户5链接上了: 用户7链接上了: Main thread end! 用户6链接上了: 用户8链接上了: 用户9链接上了: 用户3开始访问后台程序... 用户4开始访问后台程序... 用户2开始访问后台程序... 用户4访问结束。 用户3访问结束。 用户7开始访问后台程序... 用户0开始访问后台程序... 用户8开始访问后台程序... 用户2访问结束。 用户5开始访问后台程序... 用户0访问结束。 用户7访问结束。 用户1开始访问后台程序... 用户8访问结束。 用户6开始访问后台程序... 用户1访问结束。 用户9开始访问后台程序... 用户5访问结束。 用户6访问结束。 用户9访问结束。
从结果上能够看出来,10我的同时进来,可是只能同时3我的访问资源,释放一个容许进来一个
(3)参考资料
http://ifeve.com/semaphore/
第四节 Exchanger
(1)初识Exchanger
此处的Exechanger与前面描述的几个同步机制不同,前面描述的几个同步机制均是经过计数器来实现的,下面简单描述一下Exechanger,看看Exchanger的应用场景:
注意:从上文描述,咱们知道Exchanger用于在成对出现的线程之间(两个线程共有一个Exchanger)交换数据
(2)Exechanger示例
(3)参考资料
http://www.cnblogs.com/davidwang456/p/4179488.html