java并发:线程同步机制之计数器&Exechanger
第一节 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示例
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();
}
}
}
上述程序运行结果如下:
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
java并发:线程同步机制之计数器&Exechanger的更多相关文章
- Java 并发 线程同步
Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...
- java synchronized 线程同步机制详解
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...
- Java并发——线程同步Volatile与Synchronized详解
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...
- 【总结】Java线程同步机制深刻阐述
原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread ...
- Java多线程编程(4)--线程同步机制
一.锁 1.锁的概念 线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...
- Java多线程 | 02 | 线程同步机制
同步机制简介 线程同步机制是一套用于协调线程之间的数据访问的机制.该机制可以保障线程安全.Java平台提供的线程同步机制包括: 锁,volatile关键字,final关键字,static关键字,以 ...
- Java分享笔记:创建多线程 & 线程同步机制
[1] 创建多线程的两种方式 1.1 通过继承Thread类创建多线程 1.定义Thread类的子类,重写run()方法,在run()方法体中编写子线程要执行的功能. 2.创建子线程的实例对象,相当于 ...
- Java多线程的同步机制(synchronized)
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...
- java两种同步机制的实现 synchronized和reentrantlock
java两种同步机制的实现 synchronized和reentrantlock 双11加保障过去一周,趁现在有空,写一点硬货,因为在进入阿里之后工作域的原因之前很多java知识点很少用,所以记录一下 ...
随机推荐
- SQL Server(三)——增、删、改、查
一.数据库操作 create database 数据库名称 ——创建drop database 数据库名称 ——删除use 数据库名称 ——使用go 两条SQL语句之间分隔 二.表的操作 create ...
- web会话管理
http协议是无状态的协议,也就是说服务器不知道这个http连接是那个浏览器发过来的. 要标识会话的唯一,有两种方法:1 Cookie 2 会话级cookie(开关浏览器算一次会话) 和 持久化的c ...
- storm实战:基于storm,kafka,mysql的实时统计系统
公司对客户开放多个系统,运营人员想要了解客户使用各个系统的情况,在此之前,数据平台团队已经建设好了统一的Kafka消息通道. 为了保证架构能够满足业务可能的扩张后的性能要求,选用storm来处理各个应 ...
- keepalived高可用反向代理的nginx
实验系统: (1)CentOS 6.6_x86_64: (2)共有三台主机,本实验以ip地址来命名主机,即131主机.132主机.133主机. 实验前提:防火墙和selinux都关闭,主机之间时间同步 ...
- [转]MVC3缓存之一:使用页面缓存
本文转自:http://www.cnblogs.com/parry/archive/2011/03/19/OutputCache_In_MVC3.html 在以前的WebForm的开发中,在页面的头部 ...
- ARM学习篇 中断定时理解
1. 中断控制器 a. 中断处理流程 P1--摘自S3C2440A手册 P1简要阐述了S3C2440A内置中断控制器处理中断的流程: ●若某中断有自中断,则先接收子中断请求,否则,直接接受源中断. ...
- Hacker communities collection
Copy from E安全 Hack Forums: Hack Forums是目前最为理想的黑客技术学习根据地.该论坛不仅在设计上面向黑客群体,同时也适用于开发人员.博主.游戏开发者.程序员.图形设计 ...
- DPM(voc-release5) Matlab模型文件 Mat转XML
(转载请注明作者和出处 楼燚(yì)航的blog :http://www.cnblogs.com/louyihang loves baiyan/ 未经允许请勿用于商业用途) 由于目前DPM模型训练的代 ...
- NOIP2015pj求和
题目描述 一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n.每个格子上都染了一种颜色color_i用[1,m]当中的一个整数表示),并且写了一个数字number_i. 定义一种特殊的三元组:(x ...
- 使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍
使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍 使用 React.js 的渐进式 Web 应用程序:第 1 部分 - 介绍 来自译者 markzhai:大家也知道最近 ...