本文转自http://blog.csdn.net/u010942020/article/details/79352560 感谢作者
一、Java多线程总结:
  1. 描述线程的类:Runable和Thread都属于java.lang包。
  2. 内置锁synchronized属于jvm关键字,内置条件队列操作接口Object.wait()/notify()/notifyAll()属于java.lang包。
  3. 提供内存可见性和防止指令重排的volatile属于jvm关键字。
  4. 而java.util.concurrent包(J.U.C)中包含的是java并发编程中有用的一些工具类,包括几个部分: 
    • locks部分:包含在java.util.concurrent.locks包中,提供显式锁(互斥锁和速写锁)相关功能。
    • atomic部分:包含在java.util.concurrent.atomic包中,提供原子变量类相关的功能,是构建非阻塞算法的基础。
    • executor部分:散落在java.util.concurrent包中,提供线程池相关的功能。
    • collections部分:散落在java.util.concurrent包中,提供并发容器相关功能。
    • tools部分:散落在java.util.concurrent包中,提供同步工具类,如信号量、闭锁、栅栏等功能。 
二、同步工具类详解

1、Semaphore信号量:跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(permits),允许多个线程获得许可并执行。可以用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。

示例代码:

 5 public class TIJ_semaphore {6     public static void main(String[] args) { 7 ExecutorService exec = Executors.newCachedThreadPool(); 8 final Semaphore semp = new Semaphore(5); // 5 permits 9 10 for (int index = 0; index < 20; index++) { 11 final int NO = index; 12 Runnable run = new Runnable() { 13 public void run() { 14 try { // if 1 permit avaliable, thread will get a permits and go; if no permit avaliable, thread will block until 1 avaliable 15 semp.acquire(); 16 System.out.println("Accessing: " + NO); 17 Thread.sleep((long) (10000); 18 semp.release(); 19 } catch (InterruptedException e) { 20 } 21 } 22 }; 23 exec.execute(run); 24 } 25 exec.shutdown(); 26 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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

主要方法: 
1. CountDownLatch.await():将某个线程阻塞住,直到计数器count=0才恢复执行。 
2. CountDownLatch.countDown():将计数器count减1。

使用场景: 
1. 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。 
2. 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。 
3. 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。 
4. 计算并发执行某个任务的耗时。

示例代码:

public class CountDownLatchTest {  public void 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(); System.out.println("打开闭锁"); startGate.countDown(); endGate.await(); long end = System.nanoTime(); System.out.println("闭锁退出,共耗时" + (end-start)); } public static void main(String[] args) throws InterruptedException{ CountDownLatchTest test = new CountDownLatchTest(); test.timeTasks(5, test.new RunnableTask()); } class RunnableTask implements Runnable{ @Override public void run() { System.out.println("当前线程为:" + Thread.currentThread().getName()); } } 执行结果为: 打开闭锁 当前线程为:Thread-0 当前线程为:Thread-3 当前线程为:Thread-2 当前线程为:Thread-4 当前线程为:Thread-1 闭锁退出,共耗时1109195 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

3、CyclicBarrier栅栏:用于阻塞一组线程直到某个事件发生。所有线程必须同时到达栅栏位置才能继续执行下一步操作,且能够被重置以达到重复利用。而闭锁是一次性对象,一旦进入终止状态,就不能被重置。

示例代码:

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(); } } 执行结果为: 线程0第1次到达栅栏位置,等待其他线程到达 线程1第1次到达栅栏位置,等待其他线程到达 线程2第1次到达栅栏位置,等待其他线程到达 线程3第1次到达栅栏位置,等待其他线程到达 所有线程均到达栅栏位置,开始下一轮计算 线程3第2次到达栅栏位置,等待其他线程到达 线程2第2次到达栅栏位置,等待其他线程到达 线程0第2次到达栅栏位置,等待其他线程到达 线程1第2次到达栅栏位置,等待其他线程到达 所有线程

Java并发包之闭锁/栅栏/信号量(转)相关推荐

  1. Java并发包之闭锁/栅栏/信号量及并发模型和锁

    threadLocal能够为每一个线程维护变量副本,常用于在多线程中用空间换时间 进程死锁:进程死锁,指多个进程循环等待他方占有的资源而一直等待下去的局面: 进程活锁:线程1,2需要同时占有a,b才可 ...

  2. java 信号量 闭锁_Java并发包之闭锁/栅栏/信号量

    二.同步工具类详解 1.Semaphore信号量:跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(per ...

  3. java多线程并发之旅-20-同步工具类。闭锁/栅栏/信号量/阻塞队列/FutureTask

    同步工具类 同步工具类主要包括闭锁(如CountDownLatch),栅栏(如CyclicBarrier),信号量(如Semaphore)和阻塞队列(如LinkedBlockingQueue)等: F ...

  4. java并发编程笔记3-同步容器并发容器闭锁栅栏信号量

    一.同步容器: 1.Vector容器实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施.保证了线程 ...

  5. Java多线程并发编程--Java并发包(JUC)

    Java多线程并发–Java并发包(JUC) 前言 前一篇文章中,笔者已经介绍了Java多线程的一些基础知识,但是想要成为一名中高级Java程序员还必须懂得Java并发包(JUC)的知识点,而且JUC ...

  6. Java并发包下的辅助工具类

    Java并发包下为我们提供了一些辅助工具类,来简单看看如何使用 一.CountDownLatch 减法器,必须等到减法器的值为0了,才能继续往下执行.也可以将它理解为栅栏 让一些线程堵塞直到另一个线程 ...

  7. 第 5-6 课:Java 并发包中的高级同步工具 + 面试题

    Java 中的并发包指的是 java.util.concurrent(简称 JUC)包和其子包下的类和接口,它为 Java 的并发提供了各种功能支持,比如: 提供了线程池的创建类 ThreadPool ...

  8. java并发包线程池原理分析锁的深度化

    java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素 ...

  9. Java并发编程初级-未使用Java并发包的时候

    转自Java并发编程网   http://ifeve.com/java_multi_thread_programming_1_2/ 本文介绍了Java原生的多线程技术(1.2),通过详细介绍wait和 ...

最新文章

  1. 【spring】使用eclipse在没网时编写配置文件无法获取提示 解决方法
  2. 为什么打印还要另存为_锦学考研 | 打印准考证的常犯错误
  3. 深入理解JavaScript的变量作用域(转)
  4. Thinkphp中Auth认证
  5. 学习笔记之卸载远程目标进程中的DLL模块(转)
  6. android setimageresource取list的,Java ImageView.setImageTintList方法代码示例
  7. mysql数据库字段变形_详解如何利用amoeba(变形虫)实现mysql数据库读写分离
  8. 安卓开发文档_鸿蒙2.0,HarmonyOS开发体验!
  9. decode()、nvl()等用法详解
  10. extjs官网+extjs官网案例
  11. 心斋-------马克奥勒流
  12. Android8.1系统Led的控制从底层到上层的实现
  13. Altium Designer_PCB板装配图的PDF文件输出
  14. 平面设计常用标准尺寸
  15. 软萌硬核科普必读《大圣陪你学AI》
  16. 计算apk包的安装之后占用空间以及运行时占用内存
  17. 自我介绍计算机应用技术,计算机应用专业的新生自我介绍
  18. go语言宕机(panic)——程序终止运行
  19. Mybatis+MySql中字段名为保留字(关键字)的情况
  20. 海明码,码距,海明校验码

热门文章

  1. 马斯克的星际飞船SN10又炸了,但技术却向前迈出一大步!
  2. 复杂性系统面临的难题
  3. 【周末阅读】2019自动驾驶十大关键词
  4. 2018年中国人工智能100强研究报告
  5. 【学术笔记】探索大脑静息态活动中的动态信息
  6. 动图|几张动图告诉你,工业机器人无所不能!
  7. 如何体现机器智能和群体智能的关系,2018新版互联网大脑模型绘制
  8. CVPR 2018 | 腾讯AI Lab入选21篇论文详解
  9. 麦肯锡全球调研160个案例,发布5个行业34个AI应用场景
  10. 如何打造项目级硬核简历,成为一名合格的大厂工程师(必看)