第一节 CountDownLatch

(1)初识CountDownLatch

(2)详述CountDownLatch

  CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1,当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

CountDownLatch中主要方法如下:

  public CountDownLatch(int count),构造函数中的count(计数器)实际上就是闭锁需要等待的线程数量,这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。

  public void countDown(),每调用一次这个方法,在构造函数中初始化的count值就减1,通知机制是此方法来完成的。

  public void await() throws InterruptedException,调用此方法的当前线程会一直阻塞,直到计时器的值为0。

(3)CountDownLatch示例

  1. package com.test;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4.  
  5. public class CountDownLatchDemo{
  6.  
  7. public static void main(String args[]) throws Exception{
  8. CountDownLatch latch = new CountDownLatch(3);
  9. Worker worker1 = new Worker("Jack 程序员1",latch);
  10. Worker worker2 = new Worker("Rose 程序员2",latch);
  11. Worker worker3 = new Worker("Json 程序员3",latch);
  12. worker1.start();
  13. worker2.start();
  14. worker3.start();
  15.  
  16. latch.await();
  17. System.out.println("Main thread end!");
  18. }
  19.  
  20. static class Worker extends Thread {
  21. private String workerName;
  22. private CountDownLatch latch;
  23. public Worker(String workerName,CountDownLatch latch) {
  24. this.workerName = workerName;
  25. this.latch = latch;
  26. }
  27. @Override
  28. public void run() {
  29. try {
  30. System.out.println("Worker:"+workerName +" is begin.");
  31. Thread.sleep(1000L);
  32. System.out.println("Worker:"+workerName +" is end.");
  33. } catch (InterruptedException e) {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }//模仿干活;
  37. latch.countDown();
  38. }
  39. }
  40. }

上述程序运行结果如下:

  1. Worker:Rose 程序员2 is begin.
  2. Worker:Json 程序员3 is begin.
  3. Worker:Jack 程序员1 is begin.
  4. Worker:Jack 程序员1 is end.
  5. Worker:Json 程序员3 is end.
  6. Worker:Rose 程序员2 is end.
  7. 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了。

示例:

  1. package com.test;
  2. import java.util.concurrent.BrokenBarrierException;
  3. import java.util.concurrent.CyclicBarrier;
  4. public class CyclicBarrierDemo{
  5.  
  6. public static void main(String args[]) throws Exception{
  7.  
  8. CyclicBarrier barrier = new CyclicBarrier(3,new TotalTask());
  9.  
  10. BillTask worker1 = new BillTask("111",barrier);
  11. BillTask worker2 = new BillTask("222",barrier);
  12. BillTask worker3 = new BillTask("333",barrier);
  13. worker1.start();
  14. worker2.start();
  15. worker3.start();
  16. System.out.println("Main thread end!");
  17. }
  18.  
  19. static class TotalTask extends Thread {
  20. public void run() {
  21. System.out.println("所有子任务都执行完了,就开始执行主任务了。");
  22. }
  23. }
  24.  
  25. static class BillTask extends Thread {
  26. private String billName;
  27. private CyclicBarrier barrier;
  28. public BillTask(String workerName,CyclicBarrier barrier) {
  29. this.billName = workerName;
  30. this.barrier = barrier;
  31. }
  32. @Override
  33. public void run() {
  34. try {
  35. System.out.println("市区:"+billName +"运算开始:");
  36. Thread.sleep(1000L);//模仿第一次运算;
  37. System.out.println("市区:"+billName +"运算完成,等待中...");
  38. barrier.await();//假设一次运算不完,第二次要依赖第一次的运算结果。都到达这个节点之后后面才会继续执行;
  39. System.out.println("全部都结束,市区"+billName +"才开始后面的工作。");
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. } catch (BrokenBarrierException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. }
  47.  
  48. }

上述程序运行结果如下:

  1. 市区:111运算开始:
  2. 市区:333运算开始:
  3. Main thread end!
  4. 市区:222运算开始:
  5. 市区:333运算完成,等待中...
  6. 市区:222运算完成,等待中...
  7. 市区:111运算完成,等待中...
  8. 所有子任务都执行完了,就开始执行主任务了。//这句话是最后到达wait()方法的那个线程执行的
  9. 全部都结束,市区111才开始后面的工作。
  10. 全部都结束,市区222才开始后面的工作。
  11. 全部都结束,市区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个人

  1. package com.test;
  2. import java.util.concurrent.Semaphore;
  3. public class SemaphoreDemo{
  4.  
  5. public static void main(String args[]) throws Exception{
  6.  
  7. final Semaphore semaphore = new Semaphore(3);//一次只运行3个人进行访问
  8.  
  9. for(int i=0;i<10;i++) {
  10. final int no = i;
  11. Runnable thread = new Runnable() {
  12. public void run (){
  13. try {
  14. System.out.println("用户"+no+"连接上了:");
  15. Thread.sleep(300L);
  16. semaphore.acquire();//获取接下去执行的许可
  17. System.out.println("用户"+no+"开始访问后台程序...");
  18. Thread.sleep(1000L);//模仿用户访问服务过程
  19. semaphore.release();//释放允许下一个线程访问进入后台
  20. System.out.println("用户"+no+"访问结束。");
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. };
  26. new Thread(thread).start();
  27. }
  28.  
  29. System.out.println("Main thread end!");
  30. }
  31. }

上述代码运行结果如下:

  1. 用户1连接上了:
  2. 用户3连接上了:
  3. 用户4连接上了:
  4. 用户2连接上了:
  5. 用户0连接上了:
  6. 用户5连接上了:
  7. 用户7连接上了:
  8. Main thread end!
  9. 用户6连接上了:
  10. 用户8连接上了:
  11. 用户9连接上了:
  12. 用户3开始访问后台程序...
  13. 用户4开始访问后台程序...
  14. 用户2开始访问后台程序...
  15. 用户4访问结束。
  16. 用户3访问结束。
  17. 用户7开始访问后台程序...
  18. 用户0开始访问后台程序...
  19. 用户8开始访问后台程序...
  20. 用户2访问结束。
  21. 用户5开始访问后台程序...
  22. 用户0访问结束。
  23. 用户7访问结束。
  24. 用户1开始访问后台程序...
  25. 用户8访问结束。
  26. 用户6开始访问后台程序...
  27. 用户1访问结束。
  28. 用户9开始访问后台程序...
  29. 用户5访问结束。
  30. 用户6访问结束。
  31. 用户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

java并发:线程同步机制之计数器&Exechanger的更多相关文章

  1. Java 并发 线程同步

    Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...

  2. java synchronized 线程同步机制详解

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...

  3. Java并发——线程同步Volatile与Synchronized详解

    0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...

  4. 【总结】Java线程同步机制深刻阐述

    原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread ...

  5. Java多线程编程(4)--线程同步机制

    一.锁 1.锁的概念   线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...

  6. Java多线程 | 02 | 线程同步机制

    同步机制简介 ​ 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...

  7. Java分享笔记:创建多线程 & 线程同步机制

    [1] 创建多线程的两种方式 1.1 通过继承Thread类创建多线程 1.定义Thread类的子类,重写run()方法,在run()方法体中编写子线程要执行的功能. 2.创建子线程的实例对象,相当于 ...

  8. Java多线程的同步机制(synchronized)

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...

  9. java两种同步机制的实现 synchronized和reentrantlock

    java两种同步机制的实现 synchronized和reentrantlock 双11加保障过去一周,趁现在有空,写一点硬货,因为在进入阿里之后工作域的原因之前很多java知识点很少用,所以记录一下 ...

随机推荐

  1. js 数组删除指定元素

    Array.prototype.remove = function(obj) { for (var i = 0; i < this.length; i++) { var temp = this[ ...

  2. 烂泥:【解决】virtualbox启动报创建COM对象失败错误

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 今天在启动virtualbox时,发现virtualbox报创建COM对象失败错误,如下图: 查找相关资料发现很有可能是virtualbox与OS不兼容 ...

  3. 描述Linux系统开机到登陆界面的启动过程(计时2分钟)

    简述: 1.开机BIOS自检 2.MBR引导 3.grub引导菜单 4.加载内核kernel 5.启动init进程 6.读取inittab文件,执行rc.sysinit,rc等脚本 7.启动minge ...

  4. 定时器的应用---中断方式---让8个LED灯,左右各4个来回亮

    定时器的应用---中断方式---让8个LED灯,左右各4个来回亮 /*************************** 中断方式 是主程序专注于其他的事情, 待定时器中断时才执行中断子程序. ** ...

  5. ELF Format 笔记(七)—— 符号表

    最是那一低头的温柔,像一朵水莲花不胜凉风的娇羞,道一声珍重,道一声珍重,那一声珍重里有蜜甜的忧愁 —— 徐志摩 ilocker:关注 Android 安全(新手) QQ: 2597294287 符号表 ...

  6. linux线程同步(4)-自旋锁

    自旋锁与互斥量功能一样,唯一一点不同的就是互斥量阻塞后休眠让出cpu,而自旋锁阻塞后不会让出cpu,会一直忙等待,直到得到锁!!! 自旋锁在用户态使用的比较少,在内核使用的比较多!自旋锁的使用场景:锁 ...

  7. [转]backbone.js 初探

    本文转自:http://weakfi.iteye.com/blog/1391990 什么是backbone backbone不是脊椎骨,而是帮助开发重量级的javascript应用的框架. 主要提供了 ...

  8. Spring学习之AOP总结帖

    AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组 ...

  9. 设计模式——抽象工厂模式及java实现

    设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...

  10. Java开发之JSP行为

    一.Java Bean行文 1.重点说明 Java Bean行为是一组与Java Bean相关的行为,包括useBean行为.setProperty行为.getProperty行为等.Java Bea ...