Java JUC概述

2023-11-09

Java JUC(Java Util Concurrent)是 Java 平台提供的并发编程工具包,它提供了一系列的工具类和接口,用于简化多线程编程。JUC 中的类和接口都是基于 Java 平台的底层并发原语(如锁、信号量、原子变量等)实现的,可以帮助开发者更加方便和安全地完成多线程编程。

JUC 中的常用类和接口

1. Lock 和 ReentrantLock

Lock 接口是 Java 并发包中提供的一种比 synchronized 更加灵活的锁机制。它提供了更加细粒度的控制,可以实现更加复杂的线程同步操作。ReentrantLock 是 Lock 接口的一个实现类,它提供了与 synchronized 相同的互斥性和内存可见性,同时还提供了更多的高级功能,如可重入锁、公平锁等。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
    private Lock lock = new ReentrantLock();

    public void print() {
        lock.lock();
        try {
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        } finally {
            lock.unlock();
        }
    }
}

2. Condition

Condition 接口是 Lock 接口提供的一个高级功能,它可以用于实现线程之间的通信。一个 Condition 对象可以和一个 Lock 对象关联,当一个线程调用 Condition 的 await() 方法时,它会释放掉与这个 Condition 对象关联的 Lock 对象的锁,并进入等待状态;当另一个线程调用 Condition 的 signal() 或 signalAll() 方法时,它会通知一个或所有正在等待的线程恢复执行。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionDemo {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private int count = 0;

    public void produce() {
        lock.lock();
        try {
            while (count >= 10) {
                condition.await();
            }
            count++;
            System.out.println(Thread.currentThread().getName() + " produce, count = " + count);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void consume() {
        lock.lock();
        try {
            while (count <= 0) {
                condition.await();
            }
            count--;
            System.out.println(Thread.currentThread().getName() + " consume, count = " + count);
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

3. Semaphore

Semaphore 是一种计数信号量,它可以用于控制同时访问某个资源的线程数量。Semaphore 维护了一个计数器,每当一个线程访问该资源时,计数器就会减一;当计数器为零时,所有试图访问该资源的线程都会被阻塞,直到计数器大于零。

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    private Semaphore semaphore = new Semaphore(5);

    public void access() {
        try {
            semaphore.acquire();
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
}

4. CountDownLatch

CountDownLatch 是一种同步工具类,它可以让一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch 维护了一个计数器,线程调用它的 await() 方法会阻塞,直到计数器变为零;而其他线程完成操作后,可以调用 CountDownLatch 的 countDown() 方法将计数器减一。

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    private CountDownLatch countDownLatch = new CountDownLatch(3);

    public void task() {
        try {
            // 模拟耗时操作
            Thread.sleep((long) (Math.random() * 1000));
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            countDownLatch.countDown();
        }
    }

    public void start() {
        for (int i = 0; i < 3; i++) {
            new Thread(this::task).start();
        }
        try {
            countDownLatch.await();
            System.out.println("All tasks have been completed");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5. CyclicBarrier

CyclicBarrier 是一种同步工具类,它可以让一组线程在达到某个共同点之前相互等待。CyclicBarrier 维护了一个计数器和一个栅栏点,每当一个线程到达栅栏点时,计数器就会减一;当计数器为零时,所有线程就可以继续执行。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    private CyclicBarrier cyclicBarrier = new CyclicBarrier(3, () -> {
        System.out.println("All threads have arrived at the barrier");
    });

    public void task() {
        try {
            // 模拟耗时操作
            Thread.sleep((long) (Math.random() * 1000));
            System.out.println(Thread.currentThread().getName() + " has arrived at the barrier");
            cyclicBarrier.await();
            System.out.println(Thread.currentThread().getName() + " is running");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        for (int i = 0; i < 3; i++) {
            new Thread(this::task).start();
        }
    }
}

JUC 中的常用工具类

1. Executors

Executors 是一个工具类,用于创建线程池。它提供了一些静态方法,可以方便地创建不同类型的线程池。常用的方法有:

  • newFixedThreadPool(int nThreads):创建一个固定大小的线程池,该线程池中的线程数始终为 nThreads。
  • newCachedThreadPool():创建一个缓存线程池,该线程池可以根据需要创建新的线程,但在有可用线程时重用旧线程。
  • newSingleThreadExecutor():创建一个单线程池,该线程池中始终只有一个线程在工作。
  • newScheduledThreadPool(int corePoolSize):创建一个定时任务线程池,该线程池可以在指定的延迟时间后执行任务,也可以按照固定的时间间隔执行任务。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorsDemo {
    private ExecutorService executorService = Executors.newFixedThreadPool(5);

    public void execute() {
        executorService.execute(() -> {
            // 线程安全的代码
            System.out.println(Thread.currentThread().getName() + " is running");
        });
    }

    public void shutdown() {
        executorService.shutdown();
    }
}

2. Future 和 FutureTask

Future 接口表示一个异步计算的结果,它提供了一些方法,可以查询计算是否完成、等待计算完成并获取结果。FutureTask 是 Future 接口的一个实现类,它可以用于异步执行任务,并且可以在任务执行完成后获取任务的执行结果。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTaskDemo {
    private FutureTask<Integer> futureTask = new FutureTask<>(() -> {
        // 模拟耗时操作
        Thread.sleep((long) (Math.random() * 1000));
        return 1;
    });

    public void start() {
        new Thread(futureTask).start();
    }

    public void get() {
        try {
            int result = futureTask.get();
            System.out.println("Result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

3. ConcurrentHashMap

ConcurrentHashMap 是一个线程安全的哈希表,它可以在高并发的情况下提供更好的性能。它的实现原理是将整个哈希表分成多个段,每个段都是一个独立的哈希表,可以独立地进行添加、删除、修改等操作。这样,当多个线程同时访问不同的段时,就可以实现真正的并行操作,从而提高了并发性能。

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapDemo {
    private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public void put(String key, int value) {
        map.put(key, value);
    }

    public int get(String key) {
        return map.get(key);
    }
}

JUC 中的高级特性

1. AQS

AQS(AbstractQueuedSynchronizer)是 JUC 中的一个重要类,它提供了一种通用的同步框架,可以用于实现各种同步器,如锁、信号量、倒计时门栓等。AQS 的核心思想是基于一个先进先出(FIFO)的队列,来管理等待获取同步状态的线程。当一个线程获取同步状态失败时,它会被封装成一个节点,然后加入到等待队列中,等待其他线程释放同步状态后再次尝试获取。

2. ForkJoin

ForkJoin 框架是 JUC 中的一个高性能并行计算框架,它可以将一个大任务拆分成多个小任务,并行地执行这些小任务,最后将小任务的结果合并成大任务的结果。ForkJoin 框架的核心思想是“工作窃取”,即当一个线程的任务执行完毕后,它可以从其他线程的任务队列中窃取一个任务来执行,以此来实现负载均衡。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class ForkJoinDemo extends RecursiveTask<Integer> {
    private int start;
    private int end;

    public ForkJoinDemo(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        if (end - start <= 100) {
            int sum = 0;
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else {
            int mid = (start + end) / 2;
            ForkJoinDemo left = new ForkJoinDemo(start, mid);
            ForkJoinDemo right = new ForkJoinDemo(mid + 1, end);
            left.fork();
            right.fork();
            return left.join() + right.join();
        }
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinDemo task = new ForkJoinDemo(1, 1000);
        Integer result = forkJoinPool.invoke(task);
        System.out.println("Result: " + result);
    }
}

总结

Java JUC 提供了一系列的工具类和接口,用于简化多线程编程。在实际开发中,我们应该根据具体的业务需求选择合适的工具类和接口,以提高程序的并发性能和可靠性。同时,我们还应该遵守多线程编程的最佳实践,如避免死锁、竞态条件等问题,以确保程序的正确性和稳定性。

公众号请关注"果酱桑", 一起学习,一起进步!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java JUC概述 的相关文章

  • C# 与 JAVA 接口实例

    我不知道该如何回答我的问题 它是关于Android可以实例化接口的 我正在尝试用 C 来做 现在我非常确定 Java 和 C 的规则是不能创建抽象和接口的实例 但我很想知道Android是如何做到这一点的 在 Android 中你可以这样做
  • Mediaplayer 播放几次后停止播放

    我有一个按钮 按下它会播放一个随机声音剪辑 然后播放另一个声音剪辑 然后通过一个媒体播放器播放另一个声音剪辑 但是多次按下该按钮 15 20 次 后 所有音频都会停止 我在播放最后一个音频剪辑后释放媒体播放器 所以我不认为这是原因 有什么指
  • 我从 String placeName = placeText.getText().toString(); 收到空指针异常

    您好 想从编辑文本中获取地名并在地图上标记 这是我的代码 其中出现空指针异常 请帮助我应该做什么以及哪里出错了 因为我从对话框中的编辑文本字段获取地名 View layout View inflate this R layout alert
  • Android Studio:如果设置项目的背景颜色,ListView OnClick 动画将不起作用

    在我的项目中 我在 ListView 内设置了项目 由插入 ConstraintLayout 中的多个元素组成 的背景颜色 但如果背景颜色不是至少一点透明 则单击和长按的默认动画会消失 事实上 随着透明度的降低 点击元素的效果越来越不明显
  • 使用 POJO 仅更新 JOOQ 记录中已更改的字段

    我想使用 POJO 作为源来更新 JOOQ 记录中已更改的字段 Record from Object http www jooq org javadoc 3 8 x org jooq Record html from java lang O
  • 使用 Microsoft REST API - Java 将 Xbox-Live GamerTag 转换为 XUID

    我有一个 Java 应用程序 它需要能够获取用户输入的 Minecraft Bedrock Edition 玩家标签 并将其转换为给定帐户的 XUID 以便我可以将其存储起来以供稍后列入白名单和参考目的 我一直在浏览 Microsoft R
  • 在 Java 中生成 LaTeX 输出 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有用于从 Java 生成 LaTeX 输出的 Java 库 渲染乳胶 JLatex数学 https
  • Java 套接字 - 读和写

    问题 客户端没有收到任何消息 这是客户端和服务器的完整代码 CLIENT public class Client extends Socket public Client String hostName int port throws Un
  • 对象映射器 - YAMLFactory - 由于缺少 _createContentReference 方法而出现异常

    我正在使用最新的 2 13 0 版本的 jackson 当我尝试解析 YAML 文件时 出现此异常 java lang NoSuchMethodError com fasterxml jackson core io ContentRefer
  • 检查更新时 Maven 无限期挂起

    我正在使用 Maven 构建一个项目 我是新手 并且它挂起 mvn package INFO Scanning for projects INFO INFO Building Presentation Reports INFO task s
  • 如何在 PuTTY 中保存并运行 Java 文件?

    我是 AWS 亚马逊网络服务 的新手 所以这可能是一个基本问题 我在 AWS 上创建了一个 EC2 实例 我有一台 Windows 计算机 因此我使用 PUTTY 来连接 Linux 实例 连接到我的 EC2 实例后 我使用以下命令编写 J
  • 如何组合 3 个或更多 CompletionStages?

    如果有 2 个 CompletionStages 我可以将它们与thenCombine method CompletionStage a aCompletionStage getA CompletionStage b bCompletion
  • 覆盖Java中的属性[重复]

    这个问题在这里已经有答案了 在 Java 中 我最近有几个项目 我使用了这样的设计模式 public abstract class A public abstract int getProperty public class B exten
  • Tomcat下的Spring CXF Soap Web服务:找不到服务

    我正在尝试使用 CXF 和 Spring 设置一个在 Tomcat 上运行的简单 CXF Web 服务 我有一个 Web 应用程序初始化程序来引导 CXF servlet public class WebAppInitializer ext
  • Java/Hibernate - 异常:内部连接池已达到其最大大小,当前没有可用的连接

    我第一次在大学项目中使用 Hibernate 而且我还是个新手 我想我遵循了我的教授和我阅读的一些教程给出的所有指示 但我不断收到标题中的异常 Exception in thread main org hibernate Hibernate
  • 为什么从类构造函数调用的方法应该是最终的? [复制]

    这个问题在这里已经有答案了 我是一名 Java 新手 我试图理解 Oracle 网站教程中的以下行 https docs oracle com javase tutorial java IandI final html https docs
  • Java环境变量设置方法

    我已将以下行插入 bash profile export GOOGLE APPLICATION CREDENTIALS Users jun Downloads export PATH PATH GOOGLE APPLICATION CRED
  • 为什么 OOP 中静态类的最佳实践有所不同?

    我目前正在阅读有关 Java 最佳实践的内容 我发现根据这本书 https rads stackoverflow com amzn click com 0321356683我们必须优先选择静态类而不是非静态类 我记得在 C 最佳实践中 我们
  • Bipush 在 JVM 中如何工作?

    我知道 iload 接受整数 1 到 5 但是如何使用 bipush 指令扩展到更高的数字 特定整数如何与字节码一起存储 有几种不同的指令可用于推送整数常量 最小的是iconst 指令 这些只是一个字节 因为该值是在操作码本身中编码的 ic
  • RetentionPolicy CLASS 与 RUNTIME

    两者之间有什么实际区别RetentionPolicy CLASS and RetentionPolicy RUNTIME 看起来两者都被记录到字节码中 并且无论如何都可以在运行时访问 无论如何 两者都可以在运行时访问 那不是那个javado

随机推荐

  • 查看数据库某个schema下哪张表占的空间大

    为了查询schema下某个表占用的空间问题 以便处理分析问题 直接复制粘贴 改schema 即可 select TABLE NAME concat truncate data length 1024 1024 2 MB as data si
  • Cpu运作原理与机制,那么CPU如何跑的更快?

    前言 代码都是由 CPU 跑起来的 我们代码写的好与坏就决定了 CPU 的执行效率 特别是在编写计算密集型的程序 更要注重 CPU 的执行效率 否则将会大大影响系统性能 CPU 内部嵌入了 CPU Cache 高速缓存 它的存储容量很小 但
  • 数学建模中的常见模型

    数学建模中比较常见的几种模型 一 预测与预报 1 灰色预测模型 必须掌握 满足两个条件可用 数据样本点个数少 6 15个 数据呈现指数或曲线的形式 例如 可以通过极值点和稳定点来预测下一次稳定点和极值点出现的时间点 2 微分方程预测 高大上
  • 怎样改变input被选中时边框颜色

    1 当input获得焦点时 input focus outline 1px solid 000 2 输入合法时 input valid border 1px solid green 3 输入不合法时 input invalid border
  • ElasticSearch 入门教程笔记

    视频教程 狂神说Java ElasticSearch7 6 x最新完整教程通俗易懂 视频地址 https www bilibili com video BV17a4y1x7zq 拒绝白嫖 感谢狂神分享的视频教程 ElasticSearch
  • Echarts 给pie圆饼图series.data 赋值

    1 如何去掉字符串最外层的双引号 使其变成数组 var data id 32 wd 20 3 jd 113 3 id 321 wd 20 3 jd 113 3 var yy var mm yy data split for var i 0
  • 数据挖掘算法与现实生活中的应用案例

    如何分辨出垃圾邮件 如何判断一笔交易是否属于欺诈 如何判断红酒的品质和档次 扫描王是如何做到文字识别的 如何判断佚名的著作是否出自某位名家之手 如何判断一个细胞是否属于肿瘤细胞 等等 这些问题似乎都很专业 都不太好回答 但是 如果了解一点点
  • 归因分析计算因子贡献度常见的方法

    在归因分析中 我们一般都需要计算出每个因子的贡献度是多少 比如产品DAU上升 对年龄段维度进行拆解 看是不同年龄段的用户对DAU上升的贡献度是多少 一般根据指标的类型 计算贡献度的方法也不一样 下面就列出一些常见的归因分析贡献度的计算方法
  • mt4服务器显示无连接,MT4登录显示“无效账户”,“无法连接”怎么解决

    MT4账户分为实盘账户和模拟账户 小编每天都会收到很多客户实盘账号登入不上去的申请 有的客户反应账户显示登录无效 或者无连接 没有数据流 客户就会问 是不是我的账号过期不能使用 其实不是的 账户登入不上有如下几个原因 首先我先要告诉大家 一
  • ISP(图像信号处理)算法概述、工作原理、架构、处理流程

    转自 https zhuanlan zhihu com p 115321553 ISP的主要内部构成 ISP内部包含 CPU SUP IP 各种功能模块的通称 IF 等设备 ISP的控制结构 1 ISP逻辑 2 运行在其上的firmware
  • ARM 浮点运算详解

    一 早期ARM上的浮点模拟器 早期的ARM没有协处理器 所以浮点运算是由CPU来模拟的 即所需浮点运算均在浮点运算模拟器 float math emulation 上进行 需要的浮点运算 常要耗费数千个循环才能执行完毕 因此特别缓慢 直到今
  • Vue路由中,history和hash两种模式有什么区别?

    前端路由有两种模式 hash 模式和 history 模式 接下来分析这两种模式的实现方式和优缺点 hash 模式 hash 模式是一种把前端路由的路径用井号 拼接在真实 URL 后面的模式 当井号 后面的路径发生变化时 浏览器并不会重新发
  • MySQL 表连接 JOIN

    参考 表连接 前言 建表语句 测试数据 一 表连接JOIN基础 1 什么是表连接 什么是JOIN 2 表连接的分类 2 1 内连接 2 2 外连接 2 3 等值连接 2 4 自然连接 前言 建表语句 表a CREATE TABLE a ta
  • C++迭代器作为参数传递进函数使用时的注意事项

    外部函数对迭代器进行值传递而非引用 需要注意的一点是在使用迭代器作为传入参数进行迭代器运算操作的时候 作用对象仅仅是对传入迭代器的拷贝 因为在传入迭代器后函数直接对传入的对象进行拷贝操作而不访问源对象的内存空间https blog csdn
  • html 线条外阴影,怎么添加阴影边框?

    本文介绍使用CSS添加阴影边框和word文档中添加阴影边框的方法 有一定的参考价值 有需要的朋友可以参考一下 希望对大家有所帮助 CSS添加阴影边框的方法 方法1 使用box shadow属性添加阴影边框 相关推荐 css在线手册 box
  • 程序员最全的Linux命令,不全来找我随时更新!

    一 引言 1 1 Linux引言 Linux是一套免费使用和自由传播的类Unix操作系统 是一个基于POSIX和Unix的多用户 多任务 支持多线程和多CPU的操作系统 伴随着互联网的发展 Linux得到了来自全世界软件爱好者 组织 公司的
  • 常见传感器和芯片的介绍

    文章目录 一 传感器 1 1 KY xxxx系列 KY 002 KY 003 KY 004 KY 005 KY 006 KY 007 KY 008 KY 009 KY 010 KY 011 KY 012 KY 013 KY 014 KY 0
  • 虚拟服务器ftp上传权限设置,13. 为 FTP虚拟用户设置“不同文件目录”和“访问权限”...

    Re FTP 文件传输服务 FTP 服务不论在企业或教学中 是很常用的文件共享方式 它既可以做到匿名访问 也可以做到用户名和密码访问 更可以做到只能提交但不能够访问的特殊要求等等功能 本课程将一一详细演示 FTP 服务器的一般应用场景在 企
  • check allInputDimensionsSpecified() for second profile fail

    目录 yolov7 tensorrt预测时报错 在python代码里 在调用engine推理前做这样的设置即可 yolov7修改后的tenorr
  • Java JUC概述

    Java JUC Java Util Concurrent 是 Java 平台提供的并发编程工具包 它提供了一系列的工具类和接口 用于简化多线程编程 JUC 中的类和接口都是基于 Java 平台的底层并发原语 如锁 信号量 原子变量等 实现