java 栅栏_Java并发包之闭锁/栅栏/信号量(转)
本文转自http://blog.csdn.net/u010942020/article/details/79352560 感谢作者
一、Java多线程总结:
描述线程的类:Runable和Thread都属于java.lang包。
内置锁synchronized属于jvm关键字,内置条件队列操作接口Object.wait()/notify()/notifyAll()属于java.lang包。
提供内存可见性和防止指令重排的volatile属于jvm关键字。
而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
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 栅栏_Java并发包之闭锁/栅栏/信号量(转)相关推荐
- java 信号量 闭锁_Java并发包之闭锁/栅栏/信号量
二.同步工具类详解 1.Semaphore信号量:跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(per ...
- Java并发包之闭锁/栅栏/信号量及并发模型和锁
threadLocal能够为每一个线程维护变量副本,常用于在多线程中用空间换时间 进程死锁:进程死锁,指多个进程循环等待他方占有的资源而一直等待下去的局面: 进程活锁:线程1,2需要同时占有a,b才可 ...
- Java并发包之闭锁/栅栏/信号量(转)
本文转自http://blog.csdn.net/u010942020/article/details/79352560 感谢作者 一.Java多线程总结: 描述线程的类:Runable和Thread ...
- java 栅栏_Java 并发工具类(栅栏 CyclicBarrier )
CyclicBarrier适用于这样的情况:你希望创建一组任务,它们并行地执行工作,然后在下一个步骤之前等待,直到所有任务都完成.栅栏和闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. ...
- java多线程并发之旅-20-同步工具类。闭锁/栅栏/信号量/阻塞队列/FutureTask
同步工具类 同步工具类主要包括闭锁(如CountDownLatch),栅栏(如CyclicBarrier),信号量(如Semaphore)和阻塞队列(如LinkedBlockingQueue)等: F ...
- java并发编程笔记3-同步容器并发容器闭锁栅栏信号量
一.同步容器: 1.Vector容器实现了List接口,Vector实际上就是一个数组,和ArrayList类似,但是Vector中的方法都是synchronized方法,即进行了同步措施.保证了线程 ...
- saml java实现_Java 的 SAML 开发包 java-saml
软件介绍 java-saml 是 Java 的 SAML 开发包. Maven: com.onelogin java-saml 2.4.0 示例代码:Map samlData = new HashMa ...
- 【源码+教程】Java课设项目_12款最热最新Java游戏项目_Java游戏开发_Java小游戏_飞翔的小鸟_王者荣耀_超级玛丽_推箱子_黄金矿工_贪吃蛇
马上就要期末了,同学们课设做的如何了呢?本篇为大家带来了12款热门Java小游戏项目的源码和教程,助力大家顺利迎接暑假![源码+教程]Java课设项目_12款最热最新Java游戏项目_Java游戏开发 ...
- java上此类开发包非常多,想问问各位C++同仁知道什么比较好的开发包for C/C++的吗
以前一直采用apache+expat直接对付http+xml的方式来实现soap处理,java上此类开发包非常多,想问问各位C++同仁知道什么比较好的开发包for C/C++的吗? axis for ...
- 搜寻Java Card SIM开发包,跑了一趟江南科友
昨天晚上我在公司加班看GSM Java智能卡开发内容.上午我来公司基本把书上的示例程序看完.上午我就做了点这些. 下午我找到示例相关的代码贴到Eclipse的编辑窗口中,发现缺少Java Card S ...
最新文章
- Python基础学习笔记--字符串、列表
- 《数据竞赛白皮书·下篇》发布,开源办好一场数据竞赛的实践方法论
- 鸿蒙系统8月7号,主动告别安卓,华为或很快推出搭载鸿蒙系统的手机
- 使用开源CRM进行客户关系管理(2)
- 【Linux】一步一步学Linux——chage命令(92)
- 让vue-router渲染为指定的标签
- Oracle中查询、禁用、启用、删除表外键
- 相似图像识别检 —基于图像签名(LSH)
- Linux命令之 users -- 显示当前登录的用户
- 上岸 | 青椒博士毕业后未返校任教,被判返还高校41万余元
- mysql拼接两字段查询
- 人工智能在安全漏洞方面的应用_智慧消防平台的智慧在哪方面?
- 用java写出死锁的例子_【面试】请写一个java死锁的例子-Go语言中文社区
- 安卓一键清理内存_教大家安卓怎么清理内存-装修攻略
- [Campus]我的大学
- java 处理txt_java 读写 txt 文件
- Python2.6+PyQt4.8+eric4+汉化+开发教程
- freemarker ftl java_FreeMarker学习1(Ftl)
- ExifTool如何格式化日期和时间信息以进行书写
- 人到中年:最近看到的几篇好文