JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)

摘要:
CountDownLatch相当于一个减法计数器,构造方法指定一个数字,比如6,一个线程执行一次,这个数字减1,当变为0的时候,await()方法,才开始往下执行,,看这个例子CyclicBarrier的用法,字面意思:循环栅栏,这是构造方法,第一个参数parties是线程数量,第二个参数是barrierAction:最后一个线程执行完毕之后,要做的操作,重要的方法:await(),表示这个方法的

CountDownLatch 相当于一个减法计数器, 构造方法指定一个数字,比如6, 一个线程执行一次,这个数字减1, 当变为0 的时候, await()方法,才开始往下执行,,

看这个例子
JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第1张

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第2张

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第3张

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第4张

CyclicBarrier 的用法, 字面意思:循环栅栏,

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第5张

这是构造方法, 第一个参数parties 是线程数量, 第二个参数是barrierAction: 最后一个线程执行完毕之后,要做的操作 ,
JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第6张

重要的方法: await(), 表示这个方法的调用线程已经执行完毕,到达了栅栏, BrokenBarrierException 表示栅栏已破坏原因可能是其中一个线程 await() 时被中断或者超时

基本使用: 一个线程组的所有线程都执行完毕之后, 再往下执行, 再比如一个线程组的计算,最终把计算结果合并
JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第7张

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第8张

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第9张

Semaphore 的用法 信号量: 控制访问某个资源的并发数量, acquire()这个方法用来获取一个许可, 如果没有获取到就等待, release()方法用来释放这个许可, 实际应用:比如某个共享文件最大多少人访问控制

这里模拟, 业务逻辑,共10个线程,每次只能3个线程并发执行,
JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第10张

结果为:
JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第11张

读写锁 demo

public class ReentrantReadWriteLockDemo {
    public static void main(String[] args) {
        MyCashMap cash = new MyCashMap();
        //写数据,一个一个写, 写缓存的时候要保证原子性
        for (int i = 1; i <= 10; i++) {
            int temp = i;
            new Thread(()->{
                cash.putObject(Thread.currentThread().getName(),temp);
            },"线程"+String.valueOf(i)).start();
        }

        //读数据,都可以读
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                cash.getObject(Thread.currentThread().getName());
            },"线程"+String.valueOf(i)).start();
        }
    }
}
//自定义缓存
class MyCashMap{
    private Map<String,Object> map = new HashMap<>();
    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    //加入缓存,  写数据加写锁, 只能一个线程调用
    public void putObject(String key ,Object value){
        readWriteLock.writeLock().lock();
        try {
            System.out.println(key + "---" + value);
            map.put(key,value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }
    //取数据, 加读锁,都可以读取
    public void getObject(String key){
        readWriteLock.readLock().lock();
        System.out.println(map.get(key));
        readWriteLock.readLock().unlock();
    }
}

阻塞队列 BlockingQueue, 使用场景: 多线程并发处理, 线程池

异步回调类 CompletableFuture

public class test2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"runAsync--> void");
        });
        System.out.println(completableFuture.get());//null  异步执行,无返回
        //这里是 异步执行,有结果回调
        CompletableFuture<String> completableFuture1 = CompletableFuture.supplyAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "--supplyAsync-->String");
            return "异步执行结果: 123123";
        });
        System.out.println(completableFuture1.get());
    }

    /**
     * 另一个demo
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Test
    public void test01() throws ExecutionException, InterruptedException {
        C c = new C();
        String result = c.ask("1+1=?");
        System.out.println(result);
    }
}

class C {
    public String ask(String question) throws ExecutionException, InterruptedException {
        System.out.println("C 收到了一个问题, 交给D解决,C 要出去玩");
        //这里使用异步回调, 有返回
        CompletableFuture<Integer> completableFuture = doQuestion(question);
        System.out.println("C出去玩了");
        //获取D 的执行结果为
        return "D的执行结果为:"+completableFuture.get();
    }

    private CompletableFuture<Integer> doQuestion(String question) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(()->{
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "--supplyAsync-->Integer");
            return 2;
        });
        return completableFuture;
    }

}

JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)第12张

https://www.jianshu.com/p/6bac52527ca4
这里使用的CompletableFuture.supplyAsync(runnable,executor),如果没有指定executor,会默认使用ForkJoinPool这个线程池,但是这个线程池不是自定义的,不确定内部的各个参数详情,比如阻塞队列长度,ForkJoinPool是维护了一个无限长的队列来存放任务,如果长度很大很大,阻塞队列永远装不满,反而会出现OOM的风险,所以这里可以自定义线程池
关于forkJoinPool
https://blog.csdn.net/wojiao228925661/article/details/89505575

免责声明:文章转载自《JUC 并发编程--04 常用的辅助类CountDownLatch , CyclicBarrier , Semaphore , 读写锁 , 阻塞队列,CompletableFuture(异步回调)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇RocketMQ 消息偏移量 Offset 和 CommitLog利用css3制作的几个loading图下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VLC客户端和SDK的简单应用

VLC_SDK编程指南 VLC 是一款自由、开源的跨平台多媒体播放器及框架,可播放大多数多媒体文件,以及 DVD、音频 CD、VCD 及各类流媒体协议。它可以支持目前市面上大多数的视频解码,除了Real。 VLC_SDK的调用 VLC的SDK使用C语言写成,它的解码库部分的基础是FFMpeg,FFMpeg也是一套可以用来记录、转换数字音频、视频,并能将其转...

[转]如何利用ndk-stack工具查看so库的调用堆栈【代码示例】?

如何利用ndk-stack工具查看so库的调用堆栈【代码示例】? http://hi.baidu.com/subo4110/item/d00395b3bf63e4432bebe36d Step1:Android应用主文件:CPPTestActivity.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18...

C#字节取高低位以及byte和string的转换

byte a = 0xF9; string high = Convert.ToString((a & 0xf0) >> 4);//这里的位操作数以及位移的数目可以根据自己的需要修改 string low = Convert.ToString(a & 0x0f);//这里的位操作数以及位移的数目可以根据自己的需要修改 byte和s...

Preference 使用详解

极力推荐文章:欢迎收藏Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: Perference 简介 Perference 使用方法 使用XML定义Preference 使用Fragment 定义Preference...

DELPHI 字符串分割处理

DELPHI 字符串分割处理 Code 1Function FindStr(BegSprStr,EdSpStr:String;var Source:String):String;  2var  3BegStr1Len,EdSpStr2Len,BegStr1Index,EdSpStr2index:integer;  4Temp:String;  5begi...

.net 多线程的使用(Thread)

 上篇 net 同步异步   中篇 多线程的使用(Thread)   下篇 net 任务工厂实现异步多线程 Thread多线程概述  上一篇我们介绍了net 的同步与异步,我们异步演示的时候使用的是委托多线程来实现的。今天我们来细细的剖析下 多线程。 多线程的优点:可以同时完成多个任务;可以使程序的响应速度更快;可以让占用大量处理时间的任务或当前没有进...