【JAVAEE】JUC(java.util.concurrent)的常见类

这篇具有很好参考价值的文章主要介绍了【JAVAEE】JUC(java.util.concurrent)的常见类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.Callable接口

1.1简介

1.2代码演示

 1.3Runnable与Callable的区别

2.ReentrantLock

2.1ReentrantLock的常用方法

2.2ReentrantLock的代码演示

2.3ReentrantLock和synchronized的区别

3.Semaphore信号量

3.1概念

3.2代码演示

4.CountDownLatch

4.1概念

4.2代码演示


JUC是java.util.concurrent包的简称,JDK1.5之后对多线程的一种实现,这个包下放的类都和多线程有关,提供了很多工具类。

1.Callable接口

1.1简介

Callable是一个interface。相当于把线程封装了一个“返回值”,方便程序员借助多线程的方式计算得出结果。

Callable是创建线程的一种的方式,与Runnable类似。

当你的任务需要返回值时,用Callable比较好。

1.2代码演示

先定义一个线程的任务(从1加到10的结果)

    public static void main(String[] args) {
        //先定义一个线程的任务
        Callable<Integer>callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int sum=0;
                for (int i = 0; i < 10; i++) {
                    sum+=i;
                }
                return sum;
            }
        };
    }

使用FutureTask类来创建一个对象,这个对象持有callable。执行任务并获取结果。

(FutureTask是Runnable的一个实现类,所以可以传入Thread的构造方法中)

        //通过FutureTask类来创建一个对象,这个对象持有callable
        FutureTask<Integer>futureTask=new FutureTask<>(callable);
        //创建线程并指定任务
        Thread thread=new Thread(futureTask);
        //让线程执行定义好的任务
        thread.start();
        //获取线程执行的结果
        Integer result=futureTask.get();
        //打印结果
        System.out.println(result);

实现结果:

【JAVAEE】JUC(java.util.concurrent)的常见类

 1.3Runnable与Callable的区别

【JAVAEE】JUC(java.util.concurrent)的常见类

【JAVAEE】JUC(java.util.concurrent)的常见类

如上图所示:

 ①Callable实现的是Call方法,Runnable实现的是Run方法

②Callable可以返回一个结果,Runnable不能返回结果

③Callable要配合FutureTask一起使用

④Callable可以抛出异常,Runnable不可以

2.ReentrantLock

可重入互斥锁,和synchronized定位类似,都是用来实现互斥效果,保证线程安全。是基于CAS实现的一个纯用户态的锁。

2.1ReentrantLock的常用方法

常用方法:

lock():加锁,如果获取不到锁就死等

trylock():尝试加锁

unlock():解锁

常用方法的使用代码演示:

    public static void main(String[] args) throws InterruptedException {
        //创建一个ReentrantLock锁对象
        ReentrantLock reentrantLock=new ReentrantLock();
        //加锁
        reentrantLock.lock();
        //尝试加锁,死等
        reentrantLock.tryLock();
        //尝试加锁,有超时时间
        reentrantLock.tryLock(1, TimeUnit.SECONDS);
        //释放锁
        reentrantLock.unlock();
    }

2.2ReentrantLock的代码演示

模拟业务中出现异常情况时,如何释放锁:

    //模拟业务中如果出现异常情况,如何释放锁
    public static void Demo02() throws Exception {
        //创建一个ReentrantLock锁对象
        ReentrantLock reentrantLock=new ReentrantLock();
        try {
            //加锁
            reentrantLock.lock();
            //TODO:业务逻辑
            throw new Exception("业务出现异常");
        }finally {
            //保证出现异常的时候也可以释放锁
            reentrantLock.unlock();
        }

    }

演示创建一个公平锁(默认为false):

    //演示创建一个公平锁
    public static void demo03(){
        //创建一个ReentrantLock锁对象,通过构造方法,传入true时为公平锁,默认为false
        ReentrantLock reentrantLock=new ReentrantLock(true);
    }

演示创建一个读写锁:

    //演示创建一个读写锁
    public static void demo04(){
        //创建
        ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
        //获取读锁,共享锁,读与读可以同时进行
        readWriteLock.readLock();
        //获取写锁,排他锁(互斥锁),读写,写读,写写都不能共存
        readWriteLock.writeLock();
    }

ReentrantLock可以根据不同的Condition去休眠或唤醒线程。

演示:

两个条件:1.只处理男生任务

                  2.只处理女生任务

    private static ReentrantLock reentrantLock=new ReentrantLock();
    //定义不同的条件
    private static Condition boyCondition = reentrantLock.newCondition();
    private static Condition girlCondition = reentrantLock.newCondition();

    public static void demo05() throws InterruptedException {
        Thread threadBoy = new Thread(() -> {
            // 让处理男生任务的线程去休眠
            try {
                boyCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 唤醒处理女生任务的线程
            girlCondition.signalAll();
        });

        Thread threadGirl = new Thread(() -> {
            // 让处理女生任务的线程去休眠
            try {
                girlCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 唤醒处理男生任务的线程
            boyCondition.signalAll();
        });
    }

2.3ReentrantLock和synchronized的区别

区别:

①synchronized使用时不需要手动释放锁,ReentrantLock使用时需要手动释放,使用起来更灵活,但是也容易遗漏unlock

②sychronized在申请锁失败时,会一直等待锁资源,ReentrantLock可以通过trylock的方式等待一段时间就放弃

③synchronized是非公平锁,ReentrantLock默认是非公平锁。可以通过构造方法传入一个true开启公平锁模式

④synchronized是一个关键字,是JVM内部实现的,ReentrantLock是标准库的一个类,基于Java JUC实现

3.Semaphore信号量

3.1概念

信号量,用来表示“可用资源的个数”。本质上就是一个计数器。

理解信号量:

停车场外的显示屏上通常会显示当前停车场李可用的车位个数,车位个数相当于是可用资源。

1.当一辆车入场后,相当于申请一个资源,车位的个数就减一(这个称为信号量的 P 操作)

2.当一辆车离开时,相当于释放一个资源,车位的个数就加一(这个称为信号量的 V 操作)

3.停车场所有的车位就是可以显示的最大有效值

申请资源的时候,当资源已经被用完,那么线程申请的时候就会阻塞等待。

补充:当代码需要指定有限的资源个数时,可以考虑使用Semaphore来处理。

3.2代码演示

定义一个信号量,指定可用资源个数为3

    //定义一个信号量,指定可用资源个数
    private static Semaphore semaphore=new Semaphore(3);

模拟业务处理

    public static void main(String[] args) {
        //定义一个任务
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName()+"[+]申请资源");
                    //调用此方法,可用资源数减一
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"[!]申请到资源");
                    //模拟业务处理
                    TimeUnit.SECONDS.sleep(1);
                    //释放资源
                    semaphore.release();
                    System.out.println(Thread.currentThread().getName()+"[-]释放了资源");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        };

        //创建多个线程
        for (int i = 0; i < 20; i++) {
            Thread thread=new Thread(runnable);
            thread.start();
        }
    }

当申请资源满了时,就会阻塞等待。

4.CountDownLatch

4.1概念

同时等待N个任务执行结束。

理解CountDownLatch:

好像跑步比赛,10个选手依次就位,哨声响起才同时出发,所有选手都通过终点,才能结束比赛。

作用:可以设置所有的线程必须都到达某一个关键点然后再执行后续的操作。

4.2代码演示

演示跑步比赛:

定义一个CountDownLatch,参数为10代表10个选手

    //定义一个CountDownLatch
    private static CountDownLatch countDownLatch=new CountDownLatch(10);

创建线程,模拟10个选手比赛,直到10个选手都到达终点才会颁奖

    public static void main(String[] args) throws InterruptedException {
        System.out.println("所有选手各就各位");
        //创建线程,模拟跑步比赛
        for (int i = 0; i < 10; i++) {
            Thread thread=new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"出发");
                //模拟比赛过程
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //到达终点,计数减一
                countDownLatch.countDown();
                System.out.println(Thread.currentThread().getName()+"到达终点");
            },"player"+(i+1));
            thread.start();
        }
        //等待所有线程执行完成
        //一直等到countDownLatch为0时才会执行之后的代码
        countDownLatch.await();
        //颁奖
        System.out.println("开始颁奖");
    }

运行结果:

【JAVAEE】JUC(java.util.concurrent)的常见类文章来源地址https://www.toymoban.com/news/detail-447609.html

到了这里,关于【JAVAEE】JUC(java.util.concurrent)的常见类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JavaEE初阶】 Callable 接口

    Callable 是一个 interface . 相当于把线程封装了一个 “返回值”. 方便程序猿借助多线程的方式计算结果 比如我们有以下需求 创建线程计算 1 + 2 + 3 + … + 1000, 如果我们不使用 Callable 不使用 Callable的实现过程如下: 建一个类 Result , 包含一个 sum 表示最终结果, lock 表示线程同步使

    2024年02月06日
    浏览(26)
  • 如何解决java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@7566d7cf r...

    Java中的 java.util.concurrent.RejectedExecutionException 异常表示无法将任务提交到线程池中执行。这通常是因为线程池处于关闭状态或者已经达到了最大线程数,无法再接受新的任务。 要解决这个异常,你可以考虑以下几种方法: 检查线程池的状态,确保它处于可以接受新任务的状态

    2024年02月13日
    浏览(43)
  • java.util.concurrent.Executionexception 异常

    今天运行时发生了如下报错。自己捣鼓半天也没发现问题出在哪儿,感谢大佬的帮助,记录下来防止再犯。。 caused by org.apache.flink.client.program.programInvocationException: Job failed。程序调用异常。网上找了很多解决方法,都没有能够解决这个问题。 直到在报错中发现了这一行: C

    2024年02月19日
    浏览(29)
  • javaEE初阶——多线程(九)——JUC常见的类以及线程安全的集合类

    T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 此篇文章与大家分享多线程专题的最后一篇文章:关于JUC常见的类以及线程安全的集合类 如果有不足的或者错误的请您指出! 3.1Callable接口 Callable和Runnable一样,都是用来描述一个任务的 但是区别在于 ,用Callable描述的任务是有

    2024年04月25日
    浏览(31)
  • 已解决java.util.concurrent.ExecutionException异常的正确解决方法,亲测有效!!!

    已解决java.util.concurrent.ExecutionException异常的正确解决方法,亲测有效!!! java.util.concurrent.ExecutionException java.util.concurrent.ExecutionException是Java多线程编程中常见的异常之一,它表示在执行一个Callable或者Runnable任务时,任务抛出了一个异常。 下滑查看解决方法 具体解决方法可

    2024年02月11日
    浏览(25)
  • 关于报错java.lang.reflect.InaccessibleObjectException: Unable to make field private java.util.concurrent

    java.lang.reflect.InaccessibleObjectException: Unable to make field private java.util.concurrent.Callable java.util.concurrent.FutureTask.callable accessible: module java.base does not \\\"opens java.util.concurrent\\\" to unnamed module @32eebfca 假如报这种错误,只需要在Run-Edit Configurations-Modify Options-add VM options中加  假如你报的是下面

    2024年02月15日
    浏览(52)
  • JUC并发编程学习笔记(六)Callable(简单)

    callable接口和runnable接口类似,都是为了执行另外一条线程而设计的,区别是Runnable不会返回结果也不会抛出异常。 1、可以有返回值 2、可以抛出异常 3、方法不同;run()/call(); Runnable 实现Runnable接口,重写run方法,无返回值 Callable 实现Callable接口,重写call方法,有返回值,可

    2024年02月06日
    浏览(35)
  • 【问题已解决】Unrecognized option: --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED

    今天在创建java项目时,运行报错,说无法成功创建java程序。 Unrecognized option: --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. 解决办法: 1、使用最新的jdk版本 2、在第三处,选择最新的jdk版本

    2024年02月13日
    浏览(38)
  • JUC-线程Callable使用与FutureTask源码阅读

    Callable简单使用 带返回值的线程(实现implements Callable返回值类型),使用示例 FutureTask面向对象方式学习 为了定义这样一个事物“有返回结果”,暂且称之为RunnableFuture。它集合了Runnable和Future两种事物 (其中Future接口 表示了一个任务的生命周期,是一个可取消的异步运算,可

    2024年02月04日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包