JavaEE——JUC

article/2025/9/28 17:24:20
JavaEE传送门

JavaEE

JavaEE——常见的锁策略

JavaEE——CAS


目录

  • JUC
    • 1. Callable 接口
    • 2. ReentrantLock
    • 3. 原子类
    • 4. 线程池
    • 5. 信号量 Semaphore
    • 6. CountDownLatch


JUC

JUC 全称 java.util.concurrent

1. Callable 接口

类似于 Runnable. Runnable 描述的任务, 不带返回值. Callable 描述的任务是带返回值的.

示例: 创建线程, 通过线程来计算 1 + 2 + 3 + . . . + 1000

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;public class Test {public static void main(String[] args) throws ExecutionException, InterruptedException {//使用 callable 定义一个任务Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for(int i = 1; i <= 1000; i++) {sum += i;}return sum;}};//存在的意义, 就是为了我们能够获取到结果(获取到结果的凭证)FutureTask<Integer> futureTask = new FutureTask<>(callable);//创建线程来执行上述任务//Thread 的构造方法, 不能直接传 callable , 还需要一个中间的类Thread t = new Thread(futureTask);t.start();//获取线程的计算结果//get 方法会阻塞, 直到 call 方法计算完毕, get 才会返回System.out.println(futureTask.get());}
}

总结: 线程创建的方式

  1. 继承 Thread
  2. 实现 Runnable
  3. 使用 lambda
  4. 使用线程池
  5. 使用 Callable

2. ReentrantLock

可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全.

核心用法:

  1. lock( ): 加锁, 如果获取不到锁就死等
  2. tryLock(超时时间): 加锁, 如果获取不到锁, 等待一定时间之后就放弃加锁
  3. unlock( ): 解锁

小缺点

import java.util.concurrent.locks.ReentrantLock;public class Demo1 {public static void main(String[] args) {ReentrantLock locker = new ReentrantLock();//加锁locker.lock();//解锁locker.unlock();}
}

在上述代码中, 如果在 locker.lock();locker.unlock(); 之间, 出现了 return, 或者有异常, 就可能导致 unlock 执行不了.

解决方案: 使用try finally

import java.util.concurrent.locks.ReentrantLock;public class Demo1 {public static void main(String[] args) {ReentrantLock locker = new ReentrantLock();try{//加锁locker.lock();}finally {//解锁locker.unlock();}}
}

优势

ReentrantLock 有一些特定的功能, 是 sychronized 做不到的.

  1. tryLock 试试看能不能加上锁. 成功了, 就加锁成功. 试失败了, 就放弃. 并且还可以指定加锁的等待超时时间.

  2. ReentrantLock 可以实现 公平锁. (默认是非公平的), 构造的时候,传入一个简单的参数, 就成了公平锁.

    ReentrantLock locker = new ReentrantLock(true);
    
  3. sychornized 是搭配 wait/ notify 实现等待通知机制的, 唤醒操作是一个随机的过程.

    ReentrantLock 是搭配 Condition 类实现的, 可以指定唤醒哪一个等待的线程.


3. 原子类

原子类的底层, 是基于 CAS 实现的, Java 里面已经封装好了, 可以直接来使用.

使用原子类, 最常见的场景就是多线程计数, 写了个服务器, 服务器一共有多少并发量, 就可以通过这样的原子变量来累加.

示例

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;public class Test {public static void main(String[] args) throws InterruptedException {AtomicInteger count = new AtomicInteger(0);Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {// 相当于 count++count.getAndIncrement();/*// 相当于 ++countcount.incrementAndGet();// 相当于 count--count.getAndDecrement();// 相当于 count--count.decrementAndGet();*/}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {// 相当于 count++count.getAndIncrement();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}

运行结果展示


4. 线程池

JavaEE——No.2 多线程案例(内含线程池)

JavaEE——线程小知识(线程和线程池的好处)


5. 信号量 Semaphore

信号量的基本操作是两个:

  1. P 操作, 申请一个资源
  2. V操作, 释放一个资源

信号量本身是一个计数器, 表示可用资源的个数.

  • P 操作申请一个资源, 可用资源就 -1
  • V 操作释放一个资源, 可用资源就 +1
  • 当计数为 0 的时候, 继续 P 操作, 就会产生阻塞等待, 阻塞等待到其他线程 V 操作了为止.

信号量可以视为是一个更广义的锁, 锁就是一个特殊的信号量 (可用资源只有 1 的信号量)

我们把互斥锁也看做是计数为 1 的信号量.(取值只有 1 和 0, 也叫做 二元信号量)

Java 标注库提供了 Semaphore , 这个类, 其实就是把 操作系统 提供的信号量封装了一下.

示例

import java.util.concurrent.Semaphore;public class Test {public static void main(String[] args) throws InterruptedException {// 构造的时候需要指定初始值, 计数器的初始值, 表示有几个可用资源Semaphore semaphore = new Semaphore(4);// P 操作, 申请资源, 计数器 - 1semaphore.acquire();System.out.println("P 操作");semaphore.acquire();System.out.println("P 操作");semaphore.acquire();System.out.println("P 操作");semaphore.acquire();System.out.println("P 操作");semaphore.acquire();System.out.println("P 操作");// V 操作, 申请资源, 计数器 + 1semaphore.release();System.out.println("V 操作");}
}

上述代码中, 我们在只有 4 个可用资源的前提下, 进行了 5次 P 操作, 会发生什么呢?

我们发现, 进行了 4次 P操作 之后, 就开始阻塞等待, 这个阻塞会一直阻塞下去, 直到有人进行 V操作.

# 注意 #

当需求中, 有多个可用资源的时候, 要记得使用信号量.


6. CountDownLatch

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

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

使用 CountDownLatch 就是类似的效果, 使用时先设置有几个选手, 选手撞线的时候, 就调用一下 CountDownLatch 方法, 当撞线次数达到了选手的个数, 就认为比赛结束了.

示例

import java.util.concurrent.CountDownLatch;public class CountDownLatch1 {public static void main(String[] args) throws InterruptedException {// 有 10 个选手参加了比赛CountDownLatch countDownLatch = new CountDownLatch(10);for(int i = 0; i < 10; i++){//创建 10 个线程来执行一批任务Thread t = new Thread(() -> {System.out.println("选手出发! " + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("选手到达! "  + Thread.currentThread().getName());//撞线countDownLatch.countDown();});t.start();}//await 是进行阻塞等待, 会等到所有选手都撞线之后, 才结束阻塞countDownLatch.await();System.out.println("比赛结束! ");}
}

运行结果展示


🌷(( ◞•̀д•́)◞⚔◟(•̀д•́◟ ))🌷

以上就是今天要讲的内容了,希望对大家有所帮助,如果有问题欢迎评论指出,会积极改正!!
在这里插入图片描述
加粗样式

这里是Gujiu吖!!感谢你看到这里🌬
祝今天的你也
开心满怀,笑容常在。

http://chatgpt.dhexx.cn/article/5WS3ndQg.shtml

相关文章

jemalloc

项目的线上服务器&#xff0c;在code中大量使用了std::map&#xff0c;发现就存在一个问题&#xff0c;这个map使用后&#xff0c;clear后内存并不能很好的释放&#xff0c;这个主要就是std malloc的问题。可以尝试使用jemalloc和tcmalloc这些三方的malloc库。在目前我项目中&a…

Jacob简介

一、Jacob 介绍 Jacob 是 JAVA-COM Bridge的缩写&#xff0c;是一个中间件&#xff0c;能够提供自动化访问MS系统下COM组件和Win32 libraries的功能。 MS系统提供的COM组件 COM组件对象IDMS WordWord.ApplicationMS ExcelExcel.ApplicationMS PowerpointPowerpoint.Applicat…

Jacoco 入门使用

Jacoco入门使用 一、背景1. 为什么需要代码覆盖率2. 原理3. 插桩方式 二、项目实战on the fly模式(运行时插桩)1. 原理2. 配置执行2.1 环境准备2.2 以jacoco代理方式启动被测服务2.2.1 参数说明2.2.2 多种方式启动服务方式一&#xff1a;命令行方式二&#xff1a;maven插件启动…

关于jacoco的学习

目录 jacoco简单介绍 idea使用jacoco简单步骤 ANT构建 TOMCAT构建 准备工作 Tomcat配置 jacoco简单介绍 Jacoco是一个开源的覆盖率工具。Jacoco可以嵌入到Ant 、Maven中&#xff0c;并提供了EclEmma Eclipse插件,也可以使用JavaAgent技术监控Java程序。很多第三方的工具提…

JaCoCo官方教程

翻译自官方文档 1 概念 1.1 任务 - Mission JaCoCo应该为基于Java VM的环境中的代码覆盖率分析提供标准技术。重点是提供一个轻量级&#xff0c;灵活且文档齐全的库&#xff0c;以与各种构建和开发工具集成。 有几种适用于Java的开源覆盖技术。在实现Eclipse插件EclEmma时&am…

Jacoco简介

两分钟带你了解Jacoco 从测试小白一跃成为Testng专家 Java代码覆盖率实现方式有哪些 Jacoco的出发点是为基于JVM运行的代码提供代码覆盖率统计&#xff0c;期望提供轻量级的、可伸缩的、文档较全的库文件来集成各类构建和开发工具。 Java代码覆盖率工具有几款开源工具&#xff…

Maven工程加入Jacoo生成代码测试覆盖率报告

完整代码Github地址&#xff1a; https://github.com/mgljava/jacoco-demo Maven&#xff1a;Apache Maven是一个软件项目管理和理解工具。Maven基于项目对象模型(POM)的概念&#xff0c;可以从中心信息管理项目的构建、报告和文档 Jacoco&#xff1a;Java Code Coverage Lib…

Java单元覆盖率工具JaCoCo详细理解和使用(配置+示例)

一、代码覆盖率理解 代码覆盖&#xff08;Code coverage&#xff09;是软件测试中的一种度量&#xff0c;描述程序中源代码被测试的比例和程度&#xff0c;所得比例称为代码覆盖率。 简单来理解&#xff0c;就是单元测试中代码执行量与代码总量之间的比率。 Java常用的单元测试…

怎么自学C语言 入门

第一阶段&#xff1a;C语言基础 在开始学习C语言基础时&#xff0c;要反问自己为什么学C语言&#xff0c;如何学好C语言。同时要知道什么是C语言以及C语言的发展。 当对这些知识有了一个概念之后&#xff0c;就正式开始学习C语言了&#xff0c;其中&#xff0c;可能会学到数据…

C语言入门03

运算符 流程控制语句

【C语言】C语言入门经典题目(范围广,内容多)

✨作者&#xff1a;小孙的代码分享 ✨专栏&#xff1a;《C语言入门》 ✨送给各位的一句话&#xff1a;空杯心态 才能学到新知 ✨希望大家看完这些题目有所收获&#xff0c;别忘了&#xff0c;点赞评论&#xff01; 目录 前言 &#x1f604; 字符转ASCII码&#x1f525; 判断闰…

C语言入门1:Hello World

C语言入门1&#xff1a;Hello World 1、第一个C语言程序&#xff1a;Hello World&#xff01;&#xff08;1&#xff09;编辑hello.c文件&#xff08;2&#xff09;在hello.c下面编辑如下代码&#xff0c;并保存&#xff08;3&#xff09;编译hello.c文件&#xff08;4&#xf…

C语言入门(1)——Hello World

C语言入门(1)——Hello World 1. 第一个C语言程序&#xff1a;Hello World 开始的第一个程序是一个最简单的程序&#xff0c;也就是最经典的Hello World程序&#xff0c;它的功能为打印出Hello World。程序的内容非常简单&#xff0c;也是C语言编写程序的基本结构框架。 1.示…

c语言入门介绍 Hello, World

相信每一个c语言的初学者的第一个程序都是从 Hello, World! 开始的吧。不过新手刚开始接触&#xff0c;应该有许多不懂的地方&#xff0c;下面我就通过Visual Studio 2019编程环境来简单介绍一下这个程序。 第一句是由于Visual Studio 2019编程环境中scanf函数&#xff08;输入…

C语言入门的三个简易程序

文章目录 一、打印100&#xff5e;200之间的素数方法一&#xff1a;1.思路2.代码如下3.结果图 方法二:1.思路2.代码如下3.结果图 二、打印乘法口诀表1.思路2.代码如下3.结果图 三、输出1000&#xff5e;2000之间的闰年1.思路2.代码如下3.结果图 四、提升 一、打印100&#xff5…

C语言入门 九九乘法表

利用C语言 输出九九乘法表 用双重循环来完成&#xff0c;外循环用变量i控制输出的行数&#xff08;总共九行&#xff09;同时i也是被乘数。 内循环用变量j循还控制列号&#xff0c;同时j也是乘数&#xff0c;规定列号不能大于行号&#xff0c;每一行输出结束后换行。 #inclu…

C语言入门之入门

错误示范 #include<stdio.h> //头文件int mian(void){printf("你好世界&#xff01;"); //标准输出函数&#xff0c;是一个库函数return 0;}上面这个程序是有问题的&#xff0c;第一次写的时候没有运行成功 编译环境是 Visual C2010 查找之后发现是main 写…

C语言入门(初识C语言)

C语言入门&#xff08;初识C语言&#xff09; 前言什么是C语言&#xff1f;为什么选择C语言&#xff1f;计算机语言的发展高级计算机语言中的经典&#xff1a;C语言 初识C语言&#xff08;正片开始&#xff09;一.第一个C语言程序&#xff08;你好&#xff0c;C语言&#xff09…

网络流(一)最大流问题EdmondsKarp和最小费用最大流

一、最大流问题 如下图所示&#xff0c;假设需要把一些物品从结点S&#xff08;称为源点&#xff09;运送到结点t&#xff08;称为汇点&#xff09;&#xff0c;可以从其它结点中转。每条边上的权值&#xff08;左图&#xff09;表示该条路径最多能运送的物品数&#xff0c;右…

最大流,最小费用最大流:解析 + 各种板子

网络流初步 Edmond-Karp算法 网络流的基本概念 源点&#xff0c;这个点只有流量的流出&#xff0c;没有流入。汇点&#xff0c;这个点只有流量的流入&#xff0c;没有流出。容量&#xff0c;每条有向边的最大可承受的流的理论大小。流量&#xff0c;每条有向边的最大可承受的…