AQS 同步组件学习(一)

CountDownLatch 实例代码:

package com.mmall.concurrency.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class CountDownLatchExample1 {

    private final static int threadCount = 200;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        log.info("finish");
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
        Thread.sleep(100);
    }
}

semaphore : 控制并发访问的线程个数

通过提供同步机制,来控制当前访问的线程个数

tryacquire: 尝试获取可用资源,如果获取不到就丢弃

package com.mmall.concurrency.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Slf4j
public class SemaphoreExample3 {

    private final static int threadCount = 20;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    if (semaphore.tryAcquire()) { // 尝试获取一个许可
                        test(threadNum);
                        semaphore.release(); // 释放一个许可
                    }
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        log.info("{}", threadNum);
        Thread.sleep(1000);
    }
}

cyclicBarrier: 使用场景和countDownLatch的使用场景很类似,但是可以循环的使用

实现了多个线程之间的相互等待,知道所有的线程都执行完成之后,才进行下一步的操作

package com.mmall.concurrency.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CyclicBarrierExample2 {

    private static CyclicBarrier barrier = new CyclicBarrier(5);

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        try {
            barrier.await(2000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.warn("BarrierException", e);
        }
        log.info("{} continue", threadNum);
    }
}

设置达到资源屏障时优先执行的方法:

package com.mmall.concurrency.example.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class CyclicBarrierExample3 {

    private static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
        log.info("callback is running");
    });

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        log.info("{} is ready", threadNum);
        barrier.await();
        log.info("{} continue", threadNum);
    }
}

原文地址:https://www.cnblogs.com/wcgstudy/p/11509780.html

时间: 2024-07-29 19:07:49

AQS 同步组件学习(一)的相关文章

AQS 原理以及 AQS 同步组件总结

1 AQS 简单介绍 AQS 的全称为(AbstractQueuedSynchronizer),这个类在 java.util.concurrent.locks 包下面. AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLock,Semaphore,其他的诸如 ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等皆是基于 AQS 的.当然,我们自己也能利用 AQ

AQS同步组件(二)

java中锁主要分为两类: 1. synchronized 关键字修饰的锁   2. 在同步容器JUC中 ReentrantLock(可重入性) 关键字修饰的锁 ReenTrantLock 和 synchronized 的区别: 1.可重入性 ,两者都是一样的,当有线程进入锁,计数器就加1,当计数器为0的时候,释放锁 2. 锁的实现 ,Synchronized 锁是基于jvm实现的 ,而ReenTrantLock是基于JDK实现的 3.性能的区别 ,在synchronized进行性能优化之后,两

Java显式锁学习总结之二:使用AbstractQueuedSynchronizer构建同步组件

Jdk1.5中包含了并发大神Doug Lea写的并发工具包java.util.concurrent,这个工具包中包含了显示锁和其他的实用同步组件.Doug Lea在构建锁和组件的时候,大多是以队列同步器(AbstractQueuedSynchronizer)为基础的,因此AbstractQueuedSynchronizer可以看作是并发包的基础框架.因此掌握了AbstractQueuedSynchronizer的实现原理,也就掌握了大多数并发组件的实现原理. AbstractQueuedSync

AQS的几个同步组件

AQS的几个同步组件 CountDownLatch 一个线程或多个线程一直等待,直到其他线程执行的操作完成才继续执行. 应用:并行计算. 计数器是不能重计的,计数值不能往上加,类似操作只有一次. 使用时首先new一个countDownLatch,构造方法中放入计数,然后在一个线程中调用await方法,这个线程就会进入等待状态,其他线程中调用countDown方法减少这个计数,直至降到0时,await方法阻塞的线程会被唤醒继续工作,为保证顺利执行,countDown方法一定要放在finally块里

AQS同步队列器之一:介绍以及简单使用

一.简介 JDK1.5之前都是通过synchronized关键字实现并发同步,而JDK1.5以后Doug Lea大师开发了current包下的类,通过JAVA代码实现了synchronized关键的语义.然而在current包下的这些类的实现大部分都不离不开一个基础组件----AQS(AbstractQueuedSynchronizer)也就是同步队列器. AQS定义了一套多线程访问共享资源的同步框架,比如ReentrantLock.CountDownLatch等都是依赖这个基础组件实现的.深入

java实现自定义同步组件的过程

实现同步组件twinsLock:可以允许两个线程同时获取到锁,多出的其它线程将被阻塞. 以下是自定义的同步组件类,一般我们将自定义同步器Sync定义为同步组件TwinsLock的静态内部类. 实现同步器需要继承AbstractQueuedSynchronizer并覆盖相应的方法. package com.lock; import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.AbstractQueuedSynchr

Android组件学习之ExpandableListView

一个简单的小例子: 可以展开的ListView,和Listview差不多,只是设置的Adapter不同.常用的Adapter有BaseExpandableListAdapter.SimpleExpandableListAdapter.SimpleCursorTreeAdapter 布局如下:(布局中我设置了android:groupIndicator,不知道为什么不起作用.另外,android:dividerHeight这个属性是组对象和子节点共用的.如果要定义比较复杂的组视图及子节点视图,还是

如何实现自定义同步组件

package com.chen; import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.AbstractQueuedSynchronizer;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock; /** * desc:自定义同步组件,只允许最多n个线程同时访问 * // 1.共享访问 * //

Indy10 控件的使用(2)TidTCpServer组件学习

Indy10 控件的使用(2)TidTCpServer组件学习 (2012-05-18 15:16:53) 转载▼ 标签: indy10 lazarus idtcpserver 分类: Indy10 以下来自英文原版帮助文件,文桓英语不好,翻译了老半天.有错误的地方见谅,别骂我. TIdTCPServer = class(TIdComponent) Description TIdTCPServer is a TIdComponent descendant that encapsulates a