CountDownLatch 
一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数初始化CountDownLatch。调用countDown()计数减一,当计数到达零之前await()方法会一直阻塞,计数无法被重置。

public class CountDownLatch {
private final Sync sync;
public CountDownLatch(int count);
public void countDown() {
sync.releaseShared(1);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
}

CountDownLatch中主要有countDown()和await()方法。 
countDown()递减计数,如果计数达到零,则是否所有等待的线程。 
1. 如果当前计数大于零,则计数减一; 
2. 如果减一之后计数为零,则重新调度所有等待该计数为零的线程; 
3. 如果计数已经为零,则不发生任何操作; 
await()使当前线程在计数为零之前一直阻塞,除非线程被中断或超出指定的等待时间; 
如果计数为零,则立刻返回true 
在进入此方法时,当前线程已经设置了中断状态或在等待时被中断,则抛出InterruptedException异常,并且清除当前线程的中断状态。如果超出了指定等待时间,则返回false,如果该时间小于等于零,则此方法根本不会等待。

package org.github.lujiango;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; public class Test16 { public static void main(String[] args) throws InterruptedException {
final CountDownLatch begin = new CountDownLatch(1);
final CountDownLatch end = new CountDownLatch(10);
final ExecutorService exec = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
final int no = i + 1;
Runnable run = new Runnable() {
@Override
public void run() {
try {
begin.await();
TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 10000));
System.out.println("No." + no + " arrived");
} catch (Exception e) { } finally {
end.countDown();
}
}
};
exec.submit(run);
} System.out.println("Game start");
begin.countDown();
end.await();
System.out.println("Game over");
exec.shutdown();
} }

CyclicBarrier 
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点。在涉及一组固定大小的线程的程序中,这些线程必须不时的互相等待。

package org.github.lujiango;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; public class Test16 { public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
final CyclicBarrier end = new CyclicBarrier(10);
final ExecutorService exec = Executors.newFixedThreadPool(10);
System.out.println("Game start");
for (int i = 0; i < 10; i++) {
final int no = i + 1;
Runnable run = new Runnable() {
@Override
public void run() {
try {
end.await();
TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 10000));
System.out.println("No." + no + " arrived");
} catch (Exception e) { } finally {
}
}
};
exec.submit(run);
}
System.out.println("Game over");
exec.shutdown(); } }

需要所有的子任务都完成时,才执行主任务,这个时候可以选择使用CyclicBarrier。

Semaphore 
一个计数信号量,信号量维护了一个许可集,在许可可用之前会阻塞每一个acquire(),然后获取该许可。每个release()释放许可,从而可能释放一个正在阻塞的获取者。 
Semaphore只对可用许可的号码进行计数,并采取相应的行动,拿到信号的线程可以进入代码,否则就等待。

package org.github.lujiango;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; public class Test17 { public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semp = new Semaphore(5);
for (int i = 0; i < 20; i++) {
final int no = i;
Runnable run = new Runnable() { @Override
public void run() {
try {
semp.acquire();
System.out.println("Accessing: " + no);
TimeUnit.MILLISECONDS.sleep((long) (Math.random() * 10000));
} catch (Exception e) { } finally {
semp.release();
}
}
};
exec.submit(run);
}
exec.shutdown();
} }

Exchanger 
Exchanger可以在两个线程之间交换数据,只能在两个线程,不支持更多的线程之间互换数据。 
当线程A调用Exchanger对象的exchage()方法后,会阻塞;直到B线程也调用exchange()方法,然后线程以安全的方式交换数据,之后A和B线程继续执行。

package org.github.lujiango;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Exchanger; public class Test18 { public static void main(String[] args) {
Exchanger<List<Integer>> ex = new Exchanger<List<Integer>>();
new A(ex).start();
new B(ex).start();
} } class A extends Thread {
List<Integer> list = new ArrayList<Integer>();
Exchanger<List<Integer>> ex; public A(Exchanger<List<Integer>> ex) {
this.ex = ex;
} @Override
public void run() {
Random random = new Random();
for (int i = 0; i < 10; i++) {
list.clear();
list.add(random.nextInt(10));
list.add(random.nextInt(10));
list.add(random.nextInt(10));
try {
list = ex.exchange(list);
} catch (Exception e) { }
}
}
} class B extends Thread {
List<Integer> list = new ArrayList<Integer>();
Exchanger<List<Integer>> ex; public B(Exchanger<List<Integer>> ex) {
this.ex = ex;
} @Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
list = ex.exchange(list);
} catch (Exception e) { }
System.out.println(list);
}
}
}

Phaser 
Phaser是一个灵活的线程同步工具,它包含了CountDownLatch和CyclicBarrier的相关功能。 
CountDownLatch的countDown()和await()可以通过Phaser的arrive()和awaitAdvance(int n)代替 
而CyclicBarrier的await可以使用Phaser的arriveAndAwaitAdvance()方法代替 
用Phaser代替CountDownLatch:

package org.github.lujiango;

import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit; public class Test19 { public static void main(String[] args) throws InterruptedException {
final Phaser latch = new Phaser(10);
for (int i = 1; i <= 10; i++) {
final int id = i;
Thread t = new Thread(new Runnable() { @Override
public void run() {
try {
TimeUnit.SECONDS.sleep((long) (Math.random() * 10));
System.out.println("thread: " + id + " is running");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.arrive();
}
}
});
t.start();
}
latch.awaitAdvance(latch.getPhase());
System.out.println("all thread has run"); } }
package org.github.lujiango;

import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit; public class Test19 { public static void main(String[] args) throws InterruptedException {
final Phaser latch = new Phaser(10);
for (int i = 1; i <= 10; i++) {
final int id = i;
Thread t = new Thread(new Runnable() { @Override
public void run() {
try {
TimeUnit.SECONDS.sleep((long) (Math.random() * 10));
latch.arriveAndAwaitAdvance(); // 所有线程都执行到这里,才会继续执行,否则全部阻塞
System.out.println("thread: " + id + " is running");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.arrive();
}
}
});
t.start();
}
} }

  

多线程-CountDownLatch,CyclicBarrier,Semaphore,Exchanger,Phaser的更多相关文章

  1. Java中的4个并发工具类 CountDownLatch CyclicBarrier Semaphore Exchanger

    在 java.util.concurrent 包中提供了 4 个有用的并发工具类 CountDownLatch 允许一个或多个线程等待其他线程完成操作,课题点 Thread 类的 join() 方法 ...

  2. 并发工具类的使用 CountDownLatch,CyclicBarrier,Semaphore,Exchanger

    1.CountDownLatch 允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助. A CountDownLatch用给定的计数初始化. await方法阻塞,直到由于countDo ...

  3. 并发包下常见的同步工具类详解(CountDownLatch,CyclicBarrier,Semaphore)

    目录 1. 前言 2. 闭锁CountDownLatch 2.1 CountDownLatch功能简介 2.2 使用CountDownLatch 2.3 CountDownLatch原理浅析 3.循环 ...

  4. CountDownLatch/CyclicBarrier/Semaphore 使用过吗?

    CountDownLatch/CyclicBarrier/Semaphore 使用过吗?下面详细介绍用法: 一,(等待多线程完成的)CountDownLatch  背景; countDownLatch ...

  5. 并发包下常见的同步工具类(CountDownLatch,CyclicBarrier,Semaphore)

    在实际开发中,碰上CPU密集且执行时间非常耗时的任务,通常我们会选择将该任务进行分割,以多线程方式同时执行若干个子任务,等这些子任务都执行完后再将所得的结果进行合并.这正是著名的map-reduce思 ...

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

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

  7. 多线程中 CountDownLatch CyclicBarrier Semaphore的使用

    CountDownLatch 调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行.也可以传入时间,表示时间到之后,count还没有为0的时候,就会继续执行. package ...

  8. 高并发第十单:J.U.C AQS(AbstractQueuedSynchronizer) 组件:CountDownLatch. CyclicBarrier .Semaphore

    这里有一篇介绍AQS的文章 非常好: Java并发之AQS详解 AQS全名:AbstractQueuedSynchronizer,是并发容器J.U.C(java.lang.concurrent)下lo ...

  9. CountDownLatch CyclicBarrier Semaphore 比较

    document CountDownLatch A synchronization aid that allows one or more threads to wait until a set of ...

  10. 等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)

    1.main线程中先调用threadA.join() ,再调用threadB.join()实现A->B->main线程的执行顺序 调用threadA.join()时,main线程会挂起,等 ...

随机推荐

  1. 推荐一套WPF主题皮肤

    在CodePlex上发现了一套WPF的主题皮肤,直接应用于系统自带的控件,一共有四种配色方案,做得也还比较精致.感兴趣的朋友可以使用一下.点击下载      另外一套我比较喜欢的皮肤这里也推荐一下吧: ...

  2. JavaScript基础入门教程(四)

    说明 前面三篇博客介绍了js中基本的知识点,包括变量类型及其转换.表达式.运算符等小知识点,这篇博客主要讲的是对象.如果你学过java等语言,你也许在下文的阅读中发现在js中的对象与java中的对象存 ...

  3. 【FTP】使用org.apache.commons.net.ftp.FTPClient 实现FTP的上传下载

    在此之前,在项目中加上FTP的架包 第一步:配置FTP服务器的相关配置 FtpConfig.java  实体类(配置类) package com.sxd.ftp; public class FtpCo ...

  4. C/C++控制台输出时设置字体及背景颜色

    1.改变整个控制台的颜色用 system("color 0A"); 其中color后面的0是背景色代号,A是前景色代号.各颜色代码如下: 0=黑色 1=蓝色 2=绿色 3=湖蓝色  ...

  5. JAVA应用获取本机IP

    在应用开发的时候如何获取本机的IP呢? 本人在开发一个线上系统的时候有这样的需求,办法很简单啊,google一下,于是乎有了下面的代码: 方案一: Enumeration<NetworkInte ...

  6. WAF防御能力评测及工具

    本篇文章介绍如何从常规攻击的防御能力来评测一款WAF.一共覆盖了十六种攻击类型,每种类型均从利用场景(攻击操作的目的),注入点(漏洞产生的地方,比如说大多数WAF都会较全面地覆盖来自GET请求的攻击, ...

  7. Git系列三之GitHub使用方法

    GitHub 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名 GitHub. GitHub 于 2008 年 4 月 10 日正式上线,除了 Git 代 ...

  8. SQL 之 Group By

    SQL 之 Group By Group By从字面意义上理解就是根据By指定的规则对数据进行分组,所谓的分组就是将一个数据表划分成若干个小区域. 例如:有这么一张表

  9. enter 键登录的实现

    js 代码 document.onkeypress = function() { var iKeyCode = -1; if (arguments[0]) { iKeyCode = arguments ...

  10. 组件prop检验

    Vue.js中的父子组件相信都已经是大家很常用到的功能了, 父组件通过props属性向子组件传值子组件通过自定义事件向父组件传值 那么我们怎么去校验props属性中的类型呢 笔者列出以下几种方法: 1 ...