(面试必看!)一些和多线程相关的面试考点

文章导读

  • 引言
  • 考点1. CAS 指令(重点)
      • 一、什么是CAS
      • 二、CAS 的优点
      • 三、CAS 的缺点
      • 四、ABA问题
      • 五、相关面试题
  • 考点2. 信号量(semaphore)
      • 一、基本概念
      • 二、信号量的主要操作
      • 三、信号量的应用
      • 四、相关面试题
  • 考点3、CountDownLatch 类
      • 一、主要用途
      • 二、主要方法
      • 三、示例
  • 考点4、Callable 接口
      • Callable 与 Runnable 的主要区别
      • 使用场景
      • 示例
      • 相关面试题
  • 考点5、多线程下的数据结构
    • 一、多线程环境使用ArrayList
    • 二、多线程环境下使用哈希表
      • 1、Hashtable
      • 2、ConcurrentHashMap(重点)
      • 相关面试题
  • 考点五、其他常见面试题

引言

本篇文章总结了多线程中面试频率比较高的考点,内容可能比较琐碎,但是如果能够坚持看完,注意总结积累,相信对面试会有很大帮助。多线程内容较多,用一篇文章写完可能篇幅过长,我打算用两篇文章来总结,本篇主要写的是多线程中辅助加锁的数据结构和指令,下一篇主要讲的是锁策略

考点1. CAS 指令(重点)

一、什么是CAS

CAS(Compare-and-Swap)是一种用于实现多线程同步的原子指令。它涉及到三个操作数:内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值,这个操作是原子的

CAS 操作包含三个关键动作:

  1. 比较(Compare):将内存位置的值与预期原值进行比较。
  2. 交换(Swap):如果比较相等,那么处理器会自动将该内存位置的值更新为新值。
  3. 原子性(Atomicity):上述整个比较和交换的操作是原子的,即该操作在执行过程中不会被其他线程的操作打断。
    在这里插入图片描述

CAS 指令一般是基于硬件实现的,在 Intel 处理器中,它可以通过 LOCK 前缀的 CMPXCHG 指令来实现。在 Java 中,CAS 操作被广泛用于实现非阻塞算法,如原子变量类java.util.concurrent.atomic 包下的类)中的 getAndIncrementcompareAndSet 等方法都是基于 CAS 实现的。

二、CAS 的优点

  • 非阻塞算法:CAS 允许线程在不进入阻塞状态的情况下进行并发操作,这有助于减少线程切换的开销,提高系统的并发性能。
  • 无需使用锁:在多个线程竞争同一个资源时,传统的锁机制可能会导致线程阻塞,而 CAS 可以在不依赖锁的情况下实现线程间的同步。

三、CAS 的缺点

  • 循环时间长开销大:如果 CAS 操作一直不成功,那么线程会一直处于自旋状态(返回失败并持续重试),这会增加 CPU 的负担。
  • 只能保证一个共享变量的原子操作当需要对多个共享变量进行操作时,CAS 就无法保证操作的原子性了。这种情况下,需要使用锁或其他同步机制来保证操作的原子性。

四、ABA问题

  • 情景

    • 假设小明有存款1000元,他去ATM机上取100元,服务器产生了两个线程处理。线程1执行完存款变为900,线程2CAS指令比较失败,无法执行。
      在这里插入图片描述
    • 就在小明取钱的时候,小明的爸爸给小明的银行账户转了100元,产生了线程3。如果线程3是在线程1执行后才产生的,那么就会出现存款从 1000 -> 900 -> 1000 的过程,于是再执行线程2的CAS指令就会成功。本来小明只想取100元,现在取钱操作执行了两次,取出了200元!
      在这里插入图片描述
  • 定义

    在CAS操作中,线程会首先读取某个内存位置的值(我们称之为预期值A),然后执行CAS操作,尝试将该内存位置的值修改为新的值(我们称之为B),但前提是内存位置的值必须仍然是预期值A。如果在读取值和尝试修改值之间,有其他线程修改了该内存位置的值(比如从A改为了B,然后又改回了A),那么CAS操作会错误地认为该值没有变化,从而成功执行,这就会导致ABA问题。

    在以上情景中,存款从1000变900再变成1000的过程所导致的取钱两次的BUG就是ABA问题。

  • 解决方法
    给要修改的值, 引⼊版本号. 在 CAS ⽐较数据当前值和旧值的同时, 也要⽐较版本号是否符合预期。例如:
    给存款引入版本号,每次执行线程时版本号加1.
    在这里插入图片描述
    版本号为1,线程1执行扣款成功,存款为900,版本号+1变为2,线程3执行存入成功,存款为1000,版本号+1变为3,线程2执行,版本号与之前读取的不同,执行失败。

五、相关面试题

  1. 讲解下你⾃⼰理解的 CAS 机制。
  2. ABA问题怎么解决?

忠告:相关面试题的答案我不会给出,读者应自己总结积累,盲目背诵答案已经过时,面试场上的八股文已被千变万化的情景题目所取代,只有自己总结积累经验和知识才能应对变化,才能让面试官青睐!

考点2. 信号量(semaphore)

一、基本概念

  • 定义:信号量是一个非负整数,用于表示某种资源的数量。它有两个主要操作:P(等待)和V(释放)。
  • 作用:实现任务之间的同步或临界资源的互斥访问,常用于协助一组相互竞争的任务来访问临界资源。

二、信号量的主要操作

  1. P(等待)操作

    • 当一个进程或线程需要访问共享资源时,它会尝试执行P操作。
    • 如果信号量的值大于0,表示资源可用,进程或线程可以继续访问资源,并将信号量的值减1。
    • 如果信号量的值等于0,表示资源已被占用,进程或线程会被阻塞,直到信号量的值变为正数。
  2. V(释放)操作

    • 当一个进程或线程完成对共享资源的访问时,它会执行V操作,将信号量的值加1。
    • 如果有其他等待进程被阻塞,它们中的一个将被唤醒并获得对资源的访问权限。

代码示例

    public static void main(String[] args) {// 信号量为4,表明有四个资源待访问Semaphore semaphore = new Semaphore(4);// 写一个线程访问访问资源Thread t = new Thread(() -> {try {// accquire方法表示P操作semaphore.acquire();// do something ...Thread.sleep(1000);// release方法表示V操作semaphore.release();} catch(InterruptedException e){e.printStackTrace();}});t.start();}

三、信号量的应用

信号量在操作系统和并发编程中有着广泛的应用,包括但不限于:

  1. 进程同步:控制多个进程的执行顺序,保证数据的正确处理。
  2. 临界资源的互斥访问:保护共享资源,防止数据竞争和冲突。
  3. 生产者-消费者问题:在生产者-消费者模型中,通过信号量来控制资源的生产和消费。
  4. 线程池管理:控制线程池中的线程数量,以控制系统的负载。
  5. 顺序控制:确保多个任务按照特定的顺序执行。

综上所述,信号量是一种重要的同步机制,通过合理地控制信号量的值,可以实现对共享资源的互斥访问和同步操作,从而避免并发编程中的常见问题。

四、相关面试题

  1. 简单解释一下什么是信号量?
  2. 什么场景下会使用到信号量?

考点3、CountDownLatch 类

CountDownLatch 是 Java 并发包 java.util.concurrent 中的一个非常有用的同步辅助类,它允许一个或多个线程等待一组其他线程完成操作。这个类通过让一个或多个线程等待其他线程完成一组操作来协调线程。CountDownLatch 初始化时设置一个计数器(count),这个计数器代表等待完成的操作的数量。

一、主要用途

  • 等待多个线程完成CountDownLatch 允许一个或多个线程等待其他一组线程完成它们的任务。例如,在启动多个线程进行并行计算时,你可能希望等待所有线程都完成计算后再继续执行后续操作。
  • 性能优化:通过并行处理,可以提高应用程序的响应速度和吞吐量。CountDownLatch 可以帮助在并行处理完成后同步后续操作。

二、主要方法

  • CountDownLatch(int count):构造函数,初始化计数器值为给定的 count 值。
  • void await():使当前线程在锁存器倒计数至零之前一直处于等待状态,除非线程被中断。
  • void await(long timeout, TimeUnit unit):使当前线程在锁存器倒计数至零之前一直处于等待状态,或者从当前时间起已经过了指定的等待时间,或者线程被中断。
  • void countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程。

三、示例

下面是一个简单的示例,展示了如何使用 CountDownLatch 来等待一组线程完成它们的任务。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int taskCount = 5;ExecutorService executor = Executors.newFixedThreadPool(taskCount);CountDownLatch latch = new CountDownLatch(taskCount);for (int i = 0; i < taskCount; i++) {executor.submit(() -> {try {// 模拟任务执行Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}latch.countDown(); // 完成任务,减少计数器});}// 等待所有任务完成latch.await();System.out.println("所有任务完成");executor.shutdown();}
}

在这个示例中,我们创建了一个包含 5 个任务的线程池。每个任务完成后,都会调用 countDown() 方法来减少 CountDownLatch 的计数器。主线程通过调用 await() 方法等待,直到计数器的值达到 0,即所有任务都已完成。然后,主线程继续执行并打印出 “所有任务完成”。

考点4、Callable 接口

在Java中,Callable 接口是Java并发API的一部分,它位于 java.util.concurrent 包中。与 Runnable 接口不同,Callable 接口可以返回一个结果,并且可能抛出一个异常。这使得 Callable 接口非常适合用于那些需要返回值的并发任务。

Callable 接口的定义如下:

@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}

Callable 与 Runnable 的主要区别

  1. 返回值Runnable 接口的 run 方法没有返回值,而 Callable 接口的 call 方法可以返回一个泛型类型的值。
  2. 异常处理Runnablerun 方法不允许抛出受检查的异常(checked exceptions),而 Callablecall 方法可以。如果 call 方法抛出了一个异常,这个异常将被封装在一个 ExecutionException 中,这个异常是由 Future.get() 方法抛出的。

使用场景

当你需要执行一个任务,并且这个任务完成后需要返回一个结果时,就可以使用 Callable。例如,你可能需要从远程服务器获取数据,或者执行一些计算并返回结果。

示例

创建线程计算 1 + 2 + 3 + … + 1000,

使用 Run 版本

  • 创建⼀个类 Result,包含⼀个 sum 表示最终结果, lock 表⽰线程同步使⽤的锁对象。

  • main ⽅法中先创建 Result 实例, 然后创建⼀个线程 t. 在线程内部计算 1 + 2 + 3 + … + 1000.

  • 主线程同时使⽤ wait 等待线程 t 计算结束. (注意, 如果执行到 wait 之前, 线程 t 已经计算完了, 就不必等待了)。

  • 当线程 t 计算完毕后, 通过 notify 唤醒主线程, 主线程再打印结果.

public class Demo18 {static class Result {public int sum = 0;public Object lock = new Object();}public static void main(String[] args) throws InterruptedException {Result result = new Result();Thread t = new Thread() {@Overridepublic void run() {int sum = 0;for (int i = 1; i <= 1000; i++) {sum += i;}synchronized (result.lock) {result.sum = sum;result.lock.notify();}}};t.start();synchronized (result.lock) {while (result.sum == 0) {result.lock.wait();}System.out.println(result.sum);}}
}

可以看到,上述代码需要⼀个辅助类 Result,还需要使⽤⼀系列的加锁和 wait notify 操作,代码复杂,容易出错。

使用Callable版本

  • 创建⼀个匿名内部类,实现 Callable 接⼝。 Callable 带有泛型参数,泛型参数表⽰返回值的类型。
  • 重写 Callable 的 call ⽅法,完成累加的过程,直接通过返回值返回计算结果.
  • 把 callable 实例使⽤ FutureTask 包装⼀下。
  • 线程的构造⽅法传⼊ FutureTask。 此时新线程就会执行 FutureTask 内部的 Callable 的 call 方法完成计算,计算结果就放到了 FutureTask 对象中。
  • 在主线程中调⽤ futureTask.get() 能够阻塞等待新线程计算完毕. 并获取到 FutureTask 中的结果。
public class Demo18 {public static void main(String[] args) throws InterruptedException, ExecutionException {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 t = new Thread(futureTask);t.start();int result = futureTask.get();System.out.println(result);}
}

可以看到,使⽤ Callable 和 FutureTask 之后,代码简化了很多,也不必⼿动写线程同步代码了。

相关面试题

请你说说Callable 和 Runnable 的主要区别?

考点5、多线程下的数据结构

一、多线程环境使用ArrayList

  • 普通的 ArrayList 线程并不安全,在使用时必须在可能发生冲突的地方加锁,操作复杂且容易发生死锁。
  • 使用较多)使用Collections.synchronizedList(new ArrayList),synchronizedList 是标准库提供的⼀个基于 synchronized 进行线程同步的方法,它是 Collections 类的一个静态方法,它的返回值是一个对关键方法加了锁的链表(List)。这样可以简化程序猿对代码的加锁操作,降低死锁的风险。
  • 常考)使⽤ CopyOnWriteArrayList,这是一个写时复制的容器。
    • 原理:

      • 当我们往⼀个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出⼀个新的容器,然后新的容器里添加元素
      • 添加完元素之后,再将原容器的引用指向新的容器
    • 优点

      线程可以对CopyOnWrite原容器进行并发的读,而不需要加锁,因为原容器不会添加任何元素,读和写是不同的容器在读多写少的场景下,性能很高,不需要加锁竞争

    • 缺点

      占用内存较多且新写的数据不能被第⼀时间读取到

二、多线程环境下使用哈希表

HashMap 本身是线程不安全的,Java 又在 HashMap 的基础上封装了两个类:

  • Hashtable
  • ConcurrentHashMap

1、Hashtable

Hashtable 只是在 HashMap 的基础上,把关键方法加上了锁(synchronized),如:

public synchronized V get(Object key)
public synchronized V put(K key, V value)

这无疑是给所有读写操作都加上了锁,线程想要访问同一个 Hashtable 的任何数据都会直接造成锁竞争(一把锁锁上整个Hash表,如图,一个每次只能有一个线程访问该表),一旦触发扩容,就只有在单个线程(触发扩容的线程)上进行,涉及大量的数据拷贝,效率非常低。
在这里插入图片描述

2、ConcurrentHashMap(重点)

ConcurrentHashMap 是 Java 并发包 java.util.concurrent 中的一个非常重要的类,用于在并发环境下替代传统的 HashMap。它提供了比 Hashtable 更高的并发级别,因为 Hashtable 是同步的,这意味着在每一次访问时,整个表都需要被锁定,这大大降低了并发性能。ConcurrentHashMap 通过以下几个方面的优化和改进来提升并发性能:

  1. 分段锁(Segmentation Locking)(在 Java 8 之前):

    • 在 Java 8 之前,ConcurrentHashMap 使用分段锁的机制来减少锁的竞争。它将整个哈希表分为多个段(Segment),每个段都维护着自己的锁。这样,在并发环境中,只要多个线程访问的是不同的段,它们就可以并行地执行,从而减少了锁的争用。每个段内部都维护了一个哈希表,用于存储键值对。
    • 当需要对某个键进行操作时,首先通过哈希码确定该键属于哪个段,然后只锁定该段进行操作,而不是锁定整个表。
  2. 锁粒度细化(Fine-grained Locking)(在 Java 8 及以后):

    • 从 Java 8 开始,ConcurrentHashMap 放弃了分段锁的设计,转而采用了一种更为灵活的锁策略,即使用 Node 数组加上链表或红黑树(在链表过长时)的方式来存储键值对,并通过 synchronized 关键字或 CAS(Compare-And-Swap)操作来确保线程安全。
    • 在 Java 8 的实现中,锁被细化到了每个桶(bucket)上,即每个数组元素当多个线程访问不同的桶时,它们可以并行地执行。这进一步减少了锁的竞争,提高了并发性能
    • 读操作没有加锁(但是使用了 volatile 保证从内存读取结果),只对写操作进行加锁
      在这里插入图片描述
  3. 使用 CAS(Compare-And-Swap)操作:

    • CAS 是一种无锁算法,用于实现线程间的同步,而不需要使用传统的锁。在 ConcurrentHashMap 的实现中,当尝试修改某个桶(或节点)时,会尝试使用 CAS 操作来更新该桶的状态。如果桶的状态在此期间没有被其他线程修改,则 CAS 操作成功,否则重试(CAS与版本号结合)
    • CAS 操作减少了锁的使用,从而提高了性能,但也可能导致更高的 CPU 使用率,因为需要不断重试直到成功为止
  4. 动态扩容:

    • 定义
      ConcurrentHashMap 支持动态扩容,即当哈希表中的元素数量达到某个阈值时,会自动进行扩容操作,以避免哈希冲突和性能下降。与 HashMap 类似,扩容操作涉及到重新计算每个元素的哈希码,并将其放置到新的哈希表中。但 ConcurrentHashMap 的扩容操作是并发安全的可以在不阻塞读操作的情况下进行
    • 原理
      • 发现需要扩容的线程,只需要创建⼀个新的数组,同时只搬几个元素过去。
      • 扩容期间, 新老数组同时存在,后续每个来操作 ConcurrentHashMap 的线程,都会参与搬家的过程,每个操作负责搬运一小部分元素,搬完最后⼀个元素再把老数组删掉。
      • 这个期间,插入的元素只往新数组里添加,查找需要同时查新数组和⽼数组。
  5. 红黑树优化:

    • 在 Java 8 及以后的版本中,当某个桶中的链表长度超过一定阈值时(默认为 8),ConcurrentHashMap 会将该链表转换为红黑树,以优化查找性能。这是因为红黑树在查找、插入和删除操作上的时间复杂度比链表更低(在平均和最坏情况下都是 O(log n)),可以进一步提高并发性能。

综上所述,ConcurrentHashMap 通过分段锁(在 Java 8 之前)、锁粒度细化(在 Java 8 及以后)、CAS 操作、动态扩容和红黑树优化等多种机制来优化和改进并发性能,使其成为 Java 中处理并发哈希表的首选数据结构。

相关面试题

  1. ConcurrentHashMap的读是否要加锁,为什么?
  2. 介绍下 ConcurrentHashMap的锁分段技术?
  3. ConcurrentHashMap在jdk1.8做了哪些优化?
  4. Hashtable和HashMap、ConcurrentHashMap 之间的区别?

考点五、其他常见面试题

以下的面试题的答案都在我之前的文章中,大家可以从中寻找答案,这里我就不再一一赘述。

  1. 谈谈 volatile关键字的用法?

    参考文章 线程安全

  2. Java多线程是如何实现数据共享的?

    JVM 把内存分成了这几个区域; ⽅法区, 堆区, 栈区, 程序计数器。 其中堆区这个内存区域是多个线程之间共享的。只要把某个数据放到堆内存中,就可以让多个线程都能访问到。

  3. Java创建线程池的接⼝是什么?参数 LinkedBlockingQueue 的作用是什么?

    参考文章 线程池的认识和使用

  4. Java线程共有几种状态?状态之间怎么切换的?

    参考文章
    线程安全
    Thread类和线程的用法

  5. Thread和Runnable的区别和联系?

    参考文章 Thread类和线程的用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DHCP笔记

DHCP---动态主机配置协议 作用&#xff1a;为终端动态提供IP地址&#xff0c;子网掩码&#xff0c;网关&#xff0c;DNS网址等信息 具体流程 报文抓包 在DHCP服务器分配iP地址之间会进行广播发送arp报文&#xff0c;接收IP地址的设备也会发送&#xff0c;防止其他设备已经使用…

卓码软件测评:软件功能测试和非功能测试详情介绍

随着信息技术的不断发展&#xff0c;软件在我们日常生活与工作中扮演着越来越重要的角色。然而&#xff0c;软件质量的好坏直接关系到使用者的体验和企业的声誉。在软件开发过程中&#xff0c;功能测试和非功能测试作为保证软件质量的重要手段&#xff0c;受到了越来越多的关注…

古文:文天祥《正气歌》

原文 正气歌 【作者】文天祥 【朝代】宋 余囚北庭&#xff0c;坐一土室。室广八尺&#xff0c;深可四寻。单扉低小&#xff0c;白间短窄&#xff0c;污下而幽暗。当此夏日&#xff0c;诸气萃然&#xff1a;雨潦四集&#xff0c;浮动床几&#xff0c;时则为水气&#xff1b;涂泥…

YAML 语法规范

文章目录 YAML 语法规范一、简介二、基本语法三、高级语法四、示例解析五、注意事项YAML 语法规范 一、简介 YAML(YAML Ain’t Markup Language)是一种专门用来写配置文件的语言,具有简洁、易读、易解析等特点。YAML的设计理念是为人类和机器之间的沟通提供一种更加直观、…

Chiplet SPI User Guide 详细解读

目录 一. 基本介绍 1.1.整体结构 1.2. 结构细节与功能描述 二. 输入输出接口 2.1. IO Ports for SPI Leader 2.2. IO Ports for SPI Follower 2.3. SPI Mode Configuration 2.4. Leader IP和Follower IP功能图 三. SPI Programming 3.1. Leader Register Descripti…

基于FPGA的数字信号处理(19)--行波进位加法器

1、10进制加法是如何实现的&#xff1f; 10进制加法是大家在小学就学过的内容&#xff0c;不过在这里我还是帮大家回忆一下。考虑2个2位数的10进制加法&#xff0c;例如&#xff1a;15 28 43&#xff0c;它的运算过程如下&#xff1a; 个位两数相加&#xff0c;结果为5 8 1…

苹果 iCloud 钥匙串是什么?如何查看及对其进行设置?

在当今的数字世界中安全性和便利性是人们关注的两大重点。无论是社交媒体账户、还是网购平台等&#xff0c;几乎每个在线服务都需要登录账户。如何安全地管理和存储这些账户密码成为了用户们的一大挑战。 iCloud 钥匙串 我们先来看一看什么是 iCloud 钥匙串&#xff0c;iClou…

Redis:事务

1. 简介 可以一次性执行多个命令&#xff0c;本质是一组命令的集合。一个事务中的所有命令都会序列化&#xff0c;按顺序的串化执行&#xff0c;不允许被其他其他命令插入&#xff0c;不许加塞 即将要执行的命令放入队列中&#xff0c;此时该队列的所有命令就是一个事务&#x…

浏览器同源策略详解、主流的跨域解决方案、深入理解跨域请求概念及其根因

1. 什么是同源策略 跨域问题其实就是浏览器的同源策略造成的。 同源策略限制了从同一个源加载的文档或脚本如何与另一个源的资源进行交互。这是浏览器的一个用于隔离潜在恶意文件的重要的安全机制。同源指的是&#xff1a;协议、端口号、域名必须一致。 下表给出了与 URL http…

如何让你的C语言程序打印的log多一点色彩?(超级实用)

接着上一篇文章《由字节对齐引发的一场“血案“ 》 在平常的调试中&#xff0c;printf字体格式与颜色都是默认一致的。 如果可以根据log信息的重要程度&#xff0c;配以不同的颜色与格式&#xff0c;可以很方便的查找到要点。 1、printf字体显示语法说明 printf(“\033[显示…

Hive环境搭建(内置数据库)

实验目的】 1) 了解hive的作用 2) 熟练hive的配置过程&#xff08;内置数据库&#xff09; 【实验原理】 Hive的架构是由Client、Metastore、Driver、Compiler构成&#xff0c;执行流程是编译器可以将一个Hive QL转换成操作符&#xff0c;操作符是Hive中的最小处理单元。…

如何查看操作系统的性能指标:CPU、内存、磁盘、网络

目录 本系列专栏 CPU篇 CPU使用率&#xff1a;top CPU负载&#xff1a;uptime CPU核心使用情况&#xff1a;mpstat -P ALL 1 上下文切换&#xff1a;vmstat 1 CPU等待 IO时长&#xff1a;iostat -x 1 CPU的频率&#xff1a;lscpu 或者 cat /proc/cpuinfo | grep "cpu MHZ…

oracle读写时相关字符集详解

服务器端操作系统&#xff08;Oracle linux&#xff09;字符集 服务器端数据库字符集 客户端操作系统&#xff08;Oracle linux&#xff09;字符集 客户端工具sqlplus字符集 结论1&#xff1a;客户端工具sqlplus的会话&#xff0c;使用的字符集&#xff0c;是数据库字符集。…

Spring三级缓存是如何作用的

什么是三级缓存 singletonObjects&#xff1a; 一级缓存&#xff0c;用于保存实例化、注入、初始化完成的bean实例【完全体】earlySingletonObjects&#xff1a; 二级缓存&#xff0c;用于保存实例化完成的bean实例singletonFactories&#xff1a; 三级缓存&#xff0c;用于保…

java面向对象总结

java面向对象篇到这里就已经结束了&#xff0c;有什么不懂的地方可以逐一进行重新观看。希望大家能够从入门到起飞。 Java面向对象基础篇综合训练&#xff08;附带全套源代码及逐语句分析&#xff09;-&#xff1e;基于javabeen Java面向对象进阶篇综合训练&#xff08;附带全…

2024 Java 高分面试宝典 一站式搞定技术面

前言 每年9月和10月&#xff0c;被业界称为“金九银十”&#xff0c;这是人才市场一年中最活跃的时期。此时&#xff0c;企业为了来年的业务扩展&#xff0c;纷纷加大招聘力度&#xff0c;空缺岗位众多&#xff0c;招聘需求集中。同时&#xff0c;初秋的招聘活动也避开酷暑&am…

操作系统:高级IO

高级IO 1.关于IO IO的基本类型&#xff1a; I代表输入(Input): 从外部设备或来源&#xff08;如键盘、鼠标、文件、网络&#xff09;读取数据到计算机中。示例&#xff1a;用户键入的文本、从文件读取的数据、从网络接收到的数据包。 O代表输出(Output): 将计算机处理后的数据发…

git 版本回退-idea

1、选中项目&#xff0c;右键&#xff0c;打开 git历史提交记录 2、选中想要回退的版本&#xff0c;选择 hard&#xff08;不保留版本记录&#xff09; 3、最终选择强制提交&#xff08;必须强制&#xff09; OK&#xff0c;搞定

OpenCV 图像预处理—图像金字塔

文章目录 相关概念高斯金字塔拉普拉斯金字塔应用 构建高斯金字塔为什么要对当前层进行模糊&#xff1f;1. 平滑处理2. 减少混叠&#xff08;Aliasing&#xff09;3. 多尺度表示4. 图像降采样 举个栗子创建高斯金字塔和拉普拉斯金字塔&#xff0c;并用拉普拉斯金字塔恢复图像 相…

【PyTorch】基于YOLO的多目标检测项目(二)

【PyTorch】基于YOLO的多目标检测项目&#xff08;一&#xff09; 【PyTorch】基于YOLO的多目标检测项目&#xff08;二&#xff09; YOLO-v3网络由跨距为2的卷积层、跳跃连接层和上采样层组成&#xff0c;没有池化层。网络接收一幅416 * 416的图像作为输入&#xff0c;并提供三…