JUC(java.util.concurrent)的常见类
创始人
2024-05-12 05:55:39
0

在这里插入图片描述

文章目录

  • 一、JUC常见类
    • Callable 接口
    • ReentrantLock
    • Semaphore(信号量)
    • CountDownLatch

一、JUC常见类

concurrent代表了并发,这个包下为我们提供了并发编程(多线程)相关的组件.

Callable 接口

我们的Callable接口和Runnable是一样的,但也有一些区别:
Runnable: 用来描述一个任务,描述的任务是没有返回值的。
Callable: 用来描述一个任务,描述的任务是有返回值的。

所以,我们在一些场景需要线程为我们计算出某个结果的话,就可以使用Callable。

public static void main(String[] args) {Callable callable = new Callable() {@Overridepublic Integer call() throws Exception {return null;}};}

在这里插入图片描述
在这里插入图片描述
当我们直接把callable传入到Thread的构造方法里报错了,没有该构造方法,这里需要套上一层辅助类。
不能直接放进去,也很简单,因为我们的Callable是带有返回值的,可能有多个线程去执行同一个callable的任务,而且啥时候执行完并不确定,所以我们这里无法获取到返回值,FutureTask就可以负责这个等待返回值回来的工作。
在这里插入图片描述
然后我们的FutureTask为我们提供了一个get()方法,用来获取任务的返回值。
在这里插入图片描述
我们来使用Callable接口实现以下1 + 2 + … + 100

public static void main(String[] args) throws ExecutionException, InterruptedException {Callable callable = new Callable() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}return sum;}};FutureTask futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();Integer ret = futureTask.get();System.out.println(ret);}

在这里插入图片描述

ReentrantLock

ReentrantLock是标准库为我们提供的另一种锁,顾名思义。该所也是可重入锁。
我们的Synchronized也是我们标准库提供的锁,那么它们有什么区别呢?
Synchronized: 是直接基于代码块进行加锁解锁的。
ReentrantLock:是使用了lock()方法和unlock()方法进行加锁解锁的。

方法作用
lock()加锁,获取不到就死等
trylock(time 超时时间)加锁,如果一定时间内没有获取到就放弃
unlock()解锁

我们的ReentrantLock在使用起来可能有一些需要注意的事项:

在这里插入图片描述
在这里插入图片描述
我们发现系统这里提示我们lock操作必须搭配try代码块,unlock操作必须搭配finally代码块进行操作。

public static void main(String[] args) {ReentrantLock reentrantLock = new ReentrantLock();try {reentrantLock.lock();//加锁} finally {reentrantLock.unlock();//解锁}}

上述是我们ReentrantLock的劣势,当然我们ReentrantLock也是有一些优势的。

1.我们的ReentrantKLock提供了公平锁版本的实现,我们的Synchronized只实现了非公平锁。
在这里插入图片描述
2. 我们Synchronized尝试加锁,如果锁已经被占有,就进行阻塞等待(死等),ReentrantLock提供了更灵活的获取锁的方式: trylock()

方法作用
trylock()无参数,能加锁就加,加不上就放弃
trylock(time)有参数,超过指定时间,加不上锁就放弃

3.ReentrantLock提供了一个更方便的等待通知机制,Synchronized搭配的是wait,notify,当我们notify的时候是随即唤醒一个wait状态的线程。ReentrantLock搭配一个Condition类,进行唤醒的时候可以唤醒指定线程。

Semaphore(信号量)

Semaphore(信号量):信号量本质就是一个计数操作,描述"可用资源的个数",这里设计两个操作。
P操作:申请一个可用资源,计数器-1
V操作:释放一个可用资源,计数器+1

这里我们的信号量可以搭配着停车场来理解:
我们的停车场的大牌子上就写着,当前剩余车位xx个,当有车进去,就相当于进行了一次P操作,计数器-1,当有车从停车场出来,就相当于进行了一次V操作,计数器+1,当我们的停车场的剩余车位为0时,也就是计数器为0时,如果有车想停车,要么在这里等,要么就去其他停车场。
我们的Semaphore同样提供了两个方法:

方法作用
acquire申请资源
release释放资源

我们在这里设计一个场景,我们图书馆一共有5本《算法导论》,但有10个同学去借

public static void main(String[] args) {Semaphore semaphore = new Semaphore(5);Runnable runnable = new Runnable() {@Overridepublic void run() {try {System.out.println("我来借书了");semaphore.acquire();System.out.println("我拿到算法导论了!");Thread.sleep(500); //借阅时间System.out.println("我还书了");semaphore.release();} catch (InterruptedException e) {throw new RuntimeException(e);}}};for (int i = 0; i < 10; i++) {Thread t = new Thread(runnable);t.start();}}

在这里插入图片描述
我们的锁(可以认为是一个计数器为1的信号量),锁是信号量的特殊情况,信号量是锁的一般表达。
实际开发中,锁的出场频率是最高的,但也是有一些特殊的场景会用到信号量。

CountDownLatch

CountDownLatch是一个小组件,用于处理特殊场景下的。
在这里插入图片描述
就类似一场跑步比赛,开始时间是明确的,但结束时间是不确定的,只有所有选手冲线了才算结束。
像这种场景,就引入了CountDownLatch.

方法作用
CountDownLatch(人数)在构造的时候,传入一个计数(参赛选手的个数)
await()等待所有线程执行结束
countDown()表示选手冲线
public static int person;public static void main(String[] args) throws InterruptedException {CountDownLatch latch = new CountDownLatch(5);Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep((long) (Math.random() * 1000));System.out.println(person + "号选手冲线了");person++;latch.countDown();} catch (InterruptedException e) {throw new RuntimeException(e);}}};for (int i = 0; i < 5; i++) {Thread t = new Thread(runnable);t.start();}latch.await(); //等5位选手冲线System.out.println("比赛结束");}

在这里插入图片描述
在我们下载一个大型文件的时候,就可以用到CountDownLatch,比如一款游戏6个G,我们多线程下载,就可以把这个文件切分成许多小文件,多个线程同时下载,我们多线程下载是充分利用了带宽(下载是IO操作,不太涉及CPU),此处就可以用到CountDownLatch来判断整体是否下载完毕。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...