一.semaphore信号量,底层也是基于AQS
使用:
/**
* 可以理解为控制某个资源最多有多少个线程同时执行,(比如洗手间,并行与排队)
* 如果满了只能等待直到其它资源释放(可以理解为并发量控制)
* @author Binglong
* @date 2018-11-12
*/
public class SemaphoreUtils {
public static void main(String[] args) {
final int SH_SIZE = 10;
Semaphore semaphore = new Semaphore(SH_SIZE);
final int TH_NUM = 20;
for (int i = 0; i < TH_NUM; i++) {
ThreadPoolUtils.getSingle().threadPoolDo(new TaskSemaphore(semaphore));
}
}
} class TaskSemaphore implements Runnable {
private Semaphore semaphore; TaskSemaphore(Semaphore semaphore) {
this.semaphore = semaphore;
} public void run() {
String threadName = Thread.currentThread().getName();
try {
this.semaphore.acquire();
System.out.println(threadName + ":occupy...");
Thread.sleep(new Random().nextInt(10000));
System.out.println(threadName + ":over...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
    //注意一点要放到finally
semaphore.release();
}
}
}

源码

package java.util.concurrent;
import java.util.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.*; public class Semaphore implements java.io.Serializable {
private static final long serialVersionUID = -3222578661600680210L; //定义一个内部类
private final Sync sync; abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L; Sync(int permits) {
setState(permits);
} final int getPermits() {
return getState();
} final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
} protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
if (compareAndSetState(current, next))
return true;
}
} final void reducePermits(int reductions) {
for (;;) {
int current = getState();
int next = current - reductions;
if (next > current) // underflow
throw new Error("Permit count underflow");
if (compareAndSetState(current, next))
return;
}
} final int drainPermits() {
for (;;) {
int current = getState();
if (current == 0 || compareAndSetState(current, 0))
return current;
}
}
} static final class NonfairSync extends Sync {
private static final long serialVersionUID = -2694183684443567898L; NonfairSync(int permits) {
super(permits);
} protected int tryAcquireShared(int acquires) {
return nonfairTryAcquireShared(acquires);
}
} static final class FairSync extends Sync {
private static final long serialVersionUID = 2014338818796000944L; FairSync(int permits) {
super(permits);
} protected int tryAcquireShared(int acquires) {
for (;;) {
if (hasQueuedPredecessors())
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
} public Semaphore(int permits) {
sync = new NonfairSync(permits);
} public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
} public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
} public void acquireUninterruptibly() {
sync.acquireShared(1);
} public boolean tryAcquire() {
return sync.nonfairTryAcquireShared(1) >= 0;
} public boolean tryAcquire(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
} public void release() {
sync.releaseShared(1);
} public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
} public void acquireUninterruptibly(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireShared(permits);
} public boolean tryAcquire(int permits) {
if (permits < 0) throw new IllegalArgumentException();
return sync.nonfairTryAcquireShared(permits) >= 0;
} public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
} public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
} public int availablePermits() {
return sync.getPermits();
} public int drainPermits() {
return sync.drainPermits();
} protected void reducePermits(int reduction) {
if (reduction < 0) throw new IllegalArgumentException();
sync.reducePermits(reduction);
} public boolean isFair() {
return sync instanceof FairSync;
} public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
} public final int getQueueLength() {
return sync.getQueueLength();
} protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
} public String toString() {
return super.toString() + "[Permits = " + sync.getPermits() + "]";
}
}
二、CyclicBarrier
使用:
public static void main(String[] args) {
   //创建一个CyclicBarrier并在主线程上new一个任务
final int N = 5;
final CyclicBarrier cyclic = new CyclicBarrier(N, new Runnable() {
public void run() {
        //主线程任务(等最后一个线程做完)
try {
System.out.println("汇总计算开始");
Thread.sleep(Math.abs(10));
System.out.println("汇总计算完成");
} catch (Exception e) {
e.printStackTrace();
} }
}); for (int i = 0; i < N; i++) {
final int t = i;
new Thread(new Runnable() {
public void run() {
         //每个线程任务做完等待(主线程做完才继续往下走)
try {
System.out.println(t + "中心数据已计算开始");
Thread.sleep(Math.abs(new Random().nextInt() % 10000));
System.out.println(t + "中心数据已计算结束");
cyclic.await();
System.out.println(t + "中心数据退出");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
} 0中心数据已计算开始
3中心数据已计算开始
4中心数据已计算开始
2中心数据已计算开始
4中心数据已计算结束
1中心数据已计算开始
1中心数据已计算结束
3中心数据已计算结束
2中心数据已计算结束
0中心数据已计算结束
汇总计算开始
汇总计算完成
0中心数据退出
1中心数据退出
4中心数据退出
2中心数据退出
3中心数据退出
源码:
1.构造方法

//只是做等待parties个线程(没有主线程任务)
public CyclicBarrier(int parties) {
this(parties, null);
}
//等待parties个线程后,先完成barrierAction的run方法,其它线程继续执行
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
 
package java.util.concurrent;
import java.util.concurrent.locks.*; public class CyclicBarrier { private static class Generation {
boolean broken = false;
} /** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
/* The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation(); private int count; private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
} private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
} private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
     //获取锁
lock.lock();
try {
final Generation g = generation; if (g.broken)
throw new BrokenBarrierException(); if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
} int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
} // loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
} if (g.broken)
throw new BrokenBarrierException(); if (g != generation)
return index; if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
} public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
} public CyclicBarrier(int parties) {
this(parties, null);
} public int getParties() {
return parties;
} public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen;
}
} public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
} public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
} public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
} public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
}
 
 
 
2.重要方法
a.wait()方法,当调用wait()方法的线程数量,达到CyclicBarrier构造方法的N时,(CyclicBarrier在构造方法的Runnable barrierAction,方法完成后,当前线程继续执行)
在CyclicBarrier上等待的线程数量达到parties,则所有线程被释放,继续执行。
当前线程被中断,则抛出InterruptedException异常,并停止等待,继续执行。
当前线程等待超时,则抛出TimeoutException异常,并停止等待,继续执行。
其他等待的线程被中断,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。
其他等待的线程超时,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行。
其他线程调用CyclicBarrier.reset()方法,则当前线程抛出BrokenBarrierException异常,并停止等待,继续执行
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException,TimeoutException {
return dowait(true, unit.toNanos(timeout));
} public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
} b.getParties()获取CyclicBarrier等待的线程数,也就是CyclicBarrier构造方法参数parties的值 c.getNumberWaiting() how many thread wait now d.rest()
如果有正在等待的线程,则会抛出BrokenBarrierException异常,且这些线程停止等待,继续执行。
将是否破损标志位broken置为false。
 
三、CountDownLatch
使用:
/**
* countDownLatch.countDown()调用一次减一,到0时,其它await方法继续往下执行
* 可以做并发开关(把SIZE设置为1,通过主线程来countDown(),其它线程都调用await()方法)
* @author Binglong
* @date 2018-11-12
*/
public class CountDownLatchUtils {
public static void main(String[] args) throws InterruptedException {
final int SIZE = 20;
CountDownLatch countDownLatch = new CountDownLatch(SIZE);
for (int i = 0; i < SIZE; i++) {
ThreadPoolUtils.getSingle().threadPoolDo(new TaskCountDownLatch(countDownLatch));
}
System.out.println("waiting.....");
// Thread.sleep(10000);
// countDownLatch.countDown();
}
} class TaskCountDownLatch implements Runnable { private CountDownLatch countDownLatch; TaskCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
} public void run() {
String name = Thread.currentThread().getName();
try {
System.out.println(name + ":waiting.."+countDownLatch.getCount());
//等待一定数量任务继续执行
Thread.sleep(new Random().nextInt(10000));
countDownLatch.countDown();
System.out.println(name + ":over...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
1.使用
三个方法
CountDownLatch(int count):构造器中的计数值(count)。
 
void await() :会一直阻塞当前线程,直到计时器的值为0
 
void countDown():计数减一
 
 
 
 
2.原理
CountDownLatch源代码是有内部类Sync实现,而Sync是继承AQS(抽象队列同步器)
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L; Sync(int count) {
setState(count);
} int getCount() {
return getState();
} protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
} protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
} //构造器
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
} //countDown方法
public void countDown() {
//releaseShared方法是抽象队列同步器的方法
sync.releaseShared(1);
} //await方法
public void await() throws InterruptedException {
//acquireSharedInterruptibly方法是抽象队列同步器的方法
sync.acquireSharedInterruptibly(1);
}
 

J.U.C-三剑客[semaphore\CyclicBarrier\CountDownLatch]的更多相关文章

  1. 30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验?

    30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验? 前言 在本篇文章当中首先给大家介绍三个工具Semaphore, CyclicBa ...

  2. Java并发编程:Semaphore、CountDownLatch、CyclicBarrier

    首先我们来实现一个功能:当我们启动一个系统的时候需要初始化许多数据,这时候我们可能需要启动很多线程来进行数据的初始化,只有这些系统初始化结束之后才能够启动系统.其实在Java的类库中已经提供了Sema ...

  3. 【分布式锁】05-使用Redisson中Semaphore和CountDownLatch原理

    前言 前面已经写了Redisson大多的内容,我们再看看Redisson官网共有哪些组件: image.png 剩下还有Semaphore和CountDownLatch两块,我们就趁热打铁,赶紧看看R ...

  4. Redisson 分布式锁源码 11:Semaphore 和 CountDownLatch

    前言 Redisson 除了提供了分布式锁之外,还额外提供了同步组件,Semaphore 和 CountDownLatch. Semaphore 意思就是在分布式场景下,只有 3 个凭证,也就意味着同 ...

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

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

  6. JUC——线程同步辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)

    锁的机制从整体的运行转态来讲核心就是:阻塞,解除阻塞,但是如果仅仅是这点功能,那么JUC并不能称为一个优秀的线程开发框架,然而是因为在juc里面提供了大量方便的同步工具辅助类. Semaphore信号 ...

  7. 1.3.4 并发工具类CountDownLatch/Semaphore/CyclicBarrier/FutureTask

    CountDownLatch的2个用途: 1. 所有线程都到达相同的起跑线后,再一起开始跑(并非同时开始,而是队列中一个唤醒另一个)[此情况需到达起跑线后再调用await()等待其他线程] 2. 所有 ...

  8. 线程间配合:Condition、Semaphore、CountDownLatch、CyclicBarrier

    1 重入锁的好搭档:Condition条件 如果大家理解了Object.wait()和Object.notify()方法的话,那么就能很容易理解Condition接口了.它和wait()和notify ...

  9. 【Java并发编程实战】-----“J.U.C”:Semaphore

    信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是 ...

随机推荐

  1. 项目案例【Net Core】如何注入多个服务实现类

    需求 库表保存时,需要校验逻辑. 提交时有更深层次校验. **状态,还有特殊校验 接口 写一个通用的校验接口,这里定义了校验时间.每个阶段校验可能需要考虑顺序,增加一个顺序字段. public int ...

  2. Visual Studio Code自定义快捷键(eclipse习惯)

    左下角设置按钮 -> Keyboard Shortcuts -> keybindings.json. [ { "key": "alt+/", &qu ...

  3. saiku环境搭建

    说明:搭建saiku环境,BI展示工具. 环境说明: os:windows7 jdk:jdk1.6.0_43 tomcat:apache-tomcat-7.0.62 saiku:saiku-ui-2. ...

  4. vim常用命令集

    vim是vi的增强版. 这里记录下使用vim时查过的那些指令. 以备不时之需. 30j 向下移动30行 shitf + g 直接跳到文件的末尾 gg 跳回文件头 ggyG 复制全文 查找字符串 普通模 ...

  5. android等待对话框

    等待对话框,这里有两种方式来实现: ProgressDialog方式 progressDialog初始化 private void initProgressDialog() { progressDia ...

  6. android获取string.xml的值

    在android开发过程中,编写java代码中的常量过一般情况下,我们是定义在string.xml这个文件中.这样修改起来也很方便,而且做国际化也很简单. 这个string.xml的值会被R文件映射, ...

  7. 开源 , KoobooJson一款高性能且轻量的JSON框架

    KoobooJson - 更小更快的C# JSON序列化工具(基于表达式树构建) 在C#领域,有很多成熟的开源JSON框架,其中最著名且使用最多的是 Newtonsoft.Json ,然而因为版本迭代 ...

  8. Linux基础优化与安全归纳总结

    一名运维工程师在运维岗位上时间久了,就会发现Linux优化的重要性,同时会给运维工作带来很多的便利性.本人逐渐认识到了这一点,所以特意在工作闲暇之余,通过阅读Linux相关书籍及向同事.同行高手咨询, ...

  9. Singleton多种实现方式的在多线程情况下的优缺点

    一.饿汉式 缺点:不能懒加载 // 不能懒加载 public class SingletonObject1 { private static final SingletonObject1 instan ...

  10. 前端动态菜单-bootstrap-treeview

    一.bootstrap-treeview 官网 Demo bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件.该jQuery插件基于Twitter ...