Java并发编程实践 目录

并发编程 01—— ThreadLocal

并发编程 02—— ConcurrentHashMap

并发编程 03—— 阻塞队列和生产者-消费者模式

并发编程 04—— 闭锁CountDownLatch 与 栅栏CyclicBarrier

并发编程 05—— Callable和Future

并发编程 06—— CompletionService : Executor 和 BlockingQueue

并发编程 07—— 任务取消

并发编程 08—— 任务取消 之 中断

并发编程 09—— 任务取消 之 停止基于线程的服务

并发编程 10—— 任务取消 之 关闭 ExecutorService

并发编程 11—— 任务取消 之 “毒丸”对象

并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性

并发编程 13—— 线程池的使用 之 配置ThreadPoolExecutor 和 饱和策略

并发编程 14—— 线程池 之 整体架构

并发编程 15—— 线程池 之 原理一

并发编程 16—— 线程池 之 原理二

并发编程 17—— Lock

并发编程 18—— 使用内置条件队列实现简单的有界缓存

并发编程 19—— 显式的Conditon 对象

并发编程 20—— AbstractQueuedSynchronizer 深入分析

并发编程 21—— 原子变量和非阻塞同步机制

概述

第1部分 闭锁

第2部分 栅栏

参考

第1部分 闭锁

  闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态。闭锁的作用相当于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭的,并且没有任何线程能通过,当到达结束状态时,这扇门会打开并允许所有的线程通过。当闭锁到达结束状态后,将不会再改变状态,因此这扇门将永远保持打开状态。闭锁可以用来确保某些活动直到其他活动都完成后才继续执行。例如:

  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行。
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
  • 等待直到某个操作的所有参与者都就绪再继续执行。

  CountDownLatch是一种灵活的闭锁实现,可以再上述各种情况中使用,它可以使一个或多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化为一个正数,表示需要等待的事件数量。countDown方法递减计数器,表示有一个事件已经发生了,而await方法等待计数器达到0,这表示所有需要等待的事件都已经发生。如果计数器的值非零,那么await会一直阻塞直到计数器为零,或者等待中的线程中断,或者等待超时。

  下面程序TestHarness中给出了闭锁的两种常见用法。TestHarness创建一定数量的线程,利用它们并发地执行指定的任务。它使用两个闭锁,分别表示“起始门”和“结束门”。起始门计数器的初始值为1,而结束门计数器的初始值为工作线程的数量。每个工作线程首先要做到就是在启动门上等待,从而确保所有线程都就绪后才开始执行。而每个线程要做的最后一个事情是将调用结束门的countDown方法减1 ,这能使主线程高效低等待直到所有工作线程都执行完毕,因此可以统计所消耗的时间。

 package com.concurrency.BasicBuildingBlocks_5;

 import java.util.concurrent.CountDownLatch;

 /**
* 5.11 在计时测试中使用CountDownLatch来启动和停止线程(闭锁)
*
* @ClassName: TestHarness
* TODO
* @author Xingle
* @date 2014-9-4 下午2:56:29
*/
public class TestHarness { int nThreads ;
Runnable task;
public TestHarness(int nThreads,Runnable task){
this.nThreads = nThreads;
this.task = task;
}
public long timeTask(){ //起始门
final CountDownLatch startGate = new CountDownLatch(1);
//结束门
final CountDownLatch endGate = new CountDownLatch(nThreads);
for(int i = 0;i<nThreads;i++){
Thread thread = new Thread(){
public void run(){
//每个线程在启动门上等待,确保所有线程都就绪后才开始
try {
startGate.await();//等待计数器达到0
try{
task.run();
}finally{
//每个线程结束后,调用countDown递减计数器,表示一个事件发生
endGate.countDown();
}
} catch (InterruptedException e) {
e.printStackTrace();
} }
};
thread.start();
}
long start = System.nanoTime();
//启动门发生
startGate.countDown();
try {
//等待结束门的线程都结束
endGate.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.nanoTime();
return end - start;
}
}

测试程序:

 package com.concurrency.BasicBuildingBlocks_5;

 /**
*
* @ClassName: TestHarnessMain
* TODO
* @author Xingle
* @date 2014-9-4 下午3:27:18
*/
public class TestHarnessMain { public static void main(String[] args){
Runnable task = new Runnable() { @Override
public void run() {
System.out.println("执行任务,我是线程:"+Thread.currentThread().getName());
}
};
int count = 10;
TestHarness testHarness = new TestHarness(count, task );
long time = testHarness.timeTask();
System.out.println("闭锁 测试结果 执行"+count+"个线程"+" 一共用时:"+time);
}
}

执行结果:

第2部分 栅栏

上面已经看到通过闭锁来启动一组相关的操作,或者等待一组相关的操作结束。闭锁是一次性对象,一旦进入终止状态,就不能被重置。

  栅栏(Barrier)类似于闭锁,它能阻塞一组线程直到某个事件发生。栅栏与闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。(栅栏则是所有线程相互等待,直到所有线程都到达某一点时才打开栅栏,然后线程可以继续执行。)

  CyclicBarrier 可以使一定数量的参与方反复地在栅栏位置汇集,它在并行迭代算法中非常有用。CyclicBarrier支持一个可选的 Runnable 参数,当线程通过栅栏时,runnable对象将被调用。构造函数CyclicBarrier(int parties, Runnable barrierAction),当线程在CyclicBarrier对象上调用await()方法时,栅栏的计数器将增加1,当计数器为parties时,栅栏将打开。

 package com.concurrency.BasicBuildingBlocks_5;

 import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; /**
*
* @ClassName: Worker
* @author Xingle
* @date 2014-9-9 上午10:41:17
*/
public class Worker implements Runnable { final int id;
final CyclicBarrier barrier; public Worker(int id, CyclicBarrier barrier) {
this.id = id;
this.barrier = barrier;
} @Override
public void run() {
System.out.println(this.id + " start to run!");
try {
this.barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} } }

测试程序:

 package com.concurrency.BasicBuildingBlocks_5;

 import java.util.concurrent.CyclicBarrier;

 /**
*
* @ClassName: Beer
* 有五个人参与跑步,规定五个人只要都跑到终点了,大家可以喝啤酒。但是,只要有一个人没到终点,就不能喝。 这里没有要求大家要同时起跑
* @author Xingle
* @date 2014-9-9 上午10:40:36
*/
public class Beer {
public static void main(String[] args){
final int count = 5;
final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() { @Override
public void run() {
System.out.println("drink beer!");
}
}); for (int i =0; i<count;i++){
new Thread(new Worker(i, barrier)).start();
}
} }

执行结果:


参考:

1.《并发编程实战》 5.5 同步工具类

2.尽量把CyclicBarrier和CountDownLatch的区别说通俗点

并发编程 04——闭锁CountDownLatch 与 栅栏CyclicBarrier的更多相关文章

  1. 闭锁CountDownLatch与栅栏CyclicBarrier

    https://blog.csdn.net/lmc_wy/article/details/7866863   闭锁CountDownLatch与栅栏CyclicBarrier     浅谈 java ...

  2. Java并发编程之闭锁CountDownLatch简单介绍

    闭锁相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭着的,没有不论什么线程能够通过,当到达结束状态时.这扇门才会打开并容许全部线程通过.它能够使一个或多个线程等待一组事件发生. 闭锁状态包含一个 ...

  3. 并发编程-concurrent指南-回环栅栏CyclicBarrier

    字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行. java.util.concurrent.CyclicBarrier 类是一种同步机制,它能够对处理一些算法的线程实现同步 ...

  4. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  5. Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁

    Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...

  6. Java并发编程之闭锁与栅栏

    一.前言 闭锁与栅栏是在多线程编程中的概念,因为在多线程中,我们不能控制线程的执行状态,所以给线程加锁,让其按照我们的想法有秩序的执行. 闭锁 CountDownLatch,实例化时需要传入一个int ...

  7. java并发编程JUC第十篇:CyclicBarrier线程同步

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  8. Java 并发编程中的 CountDownLatch 锁用于多个线程同时开始运行或主线程等待子线程结束

    Java 5 开始引入的 Concurrent 并发软件包里面的 CountDownLatch 其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是 ...

  9. JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)

    CountDownLatch 相当于一个减法计数器, 构造方法指定一个数字,比如6, 一个线程执行一次,这个数字减1, 当变为0 的时候, await()方法,才开始往下执行,, 看这个例子 Cycl ...

随机推荐

  1. MVC控制器获取@Html.DropDownList值

    MVC控制器获取@Html.DropDownList值 发表于 2014 年 4 月 1 日 作者 efour — 暂无评论 先贴一段代码,演示@Html.DropDownList的使用. 前台 前台 ...

  2. winform listview控件

    ListView控件 1.常用的基本属性: (1)FullRowSelect:设置是否行选择模式.(默认为false) 提示:只有在Details视图该属性才有意义. (2) GridLines:设置 ...

  3. Centos 安装 Java

    建立文件夹 进入/usr/文件夹下,建立一个文件,我这里是java文件夹,将jdk-8u45-linux-x64.tar.gz复制到/usr/java文件夹下 解压文件 解压指令为:tar -zxvf ...

  4. JS中同名函数有效执行顺序

    html中如果出现函数同名时:如果有多个外部引入的js文件,例如a.js和b.js(引入顺序假定是a.js,然后是b.js),同时html中本身也有内部的js.那么针对 出现函数名一样的情况时,无论他 ...

  5. 【001:ubuntu下搭建ESP8266开发环境--编辑 编译 下载】

    系统环境:ubuntu 16.04 TLS 64BIT 编辑器: Eclipse CDT 版本 编译器:xtensa-lx106-elf 交叉编译工具链 下载工具:esptool.py pyseria ...

  6. python日志模块

    许多应用程序中都会有日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系 统的运行状况进行跟踪.在.NET平台中,有非常著名的第三方开源日志组件log4net,c++中,有人们熟悉的log4c ...

  7. oracle 面试题

    1.对数据库SQL2005.ORACLE熟悉吗?   SQL2005是微软公司的数据库产品.是一个RDBMS数据库,一般应用在一些中型数据库的应用,不能跨平台.   ORACLE是ORACLE公司的数 ...

  8. 智能家居常用WiFi模块

    WiFi模块 WiFi模块就是整个系统的控制中心,控制很简单,就是输出一个开关信号控制继电器,而这个模块的核心是WiFi的连接,手机连接WiFi时需要扫描,输入密码,而这类本身没有屏幕和键盘的硬件设备 ...

  9. Hibernate 简单使用

    首先在数据库中创建相应的表,脚本如下: create table Student (id int primary key, sName ), sNO ), sex ), email )) 在Myecl ...

  10. MVC(一)

    Webform请求模式 MVC请求模式 第一个及以下引用点击属性,拷贝到本地,在部署MVC时,将所有引用属性都改为拷贝到本地编译 建立控制器与视图 建立路由 {}标志占位符 将系统自动建立MVC项目V ...