JUC、MySQL

java后端面试题大全

  • 1.JUC
    • 1.1 ReentrantLock(可重入独占式锁)(难度:★★★ 频率:★★)
    • 1.2 ReentrantLock比synchronized的优点(难度:★★★ 频率:★★)
    • 1.3 CAS的原理和优缺点
    • 1.4 synchronized与Lock的区别(难度:★★ 频率:★★★★)
    • 1.5 常用的原子类有哪些, 它们是如何保证原子性的?

1.JUC

JUC指的是Java Util Concurrent(java工具中的并发工具), 是 Java SE 5.0 版本之后引入的一个用于支持并发编程的扩展包。

JUC 提供了一组强大的工具和框架,用于更方便、更安全地处理多线程编程的问题。

  • Executor 框架
    提供了一套用于管理线程池的接口和类,例如 ExecutorService、ThreadPoolExecutor 等,用于简化多线程任务的管理和执行。
  • 并发集合类
    提供了一些线程安全的集合类,例如 ConcurrentHashMap、ConcurrentLinkedQueue 等,用于在多线程环境下安全地操作集合
  • Lock 框架
    引入了显式的锁机制,例如 ReentrantLock,允许更灵活地进行同步操作。
  • Atomic 变量
    提供了一系列原子变量类,如 AtomicInteger、AtomicLong,用于在没有锁的情况下进行原子性操作。
  • 并发工具类
    包括 CountDownLatch、CyclicBarrier、Semaphore 等,用于协调多个线程的执行。
  • Fork/Join 框架
    提供了一种用于并行计算的框架,用于处理任务的分解和合并。
  • 并发设计模式
    提供了一些支持并发编程的设计模式,例如生产者-消费者模式、读写锁等。

1.1 ReentrantLock(可重入独占式锁)(难度:★★★ 频率:★★)

它实现了 Lock 接口。与传统的 synchronized 关键字相比,ReentrantLock 提供了更多的灵活性和功能。

  • 可重入性(Reentrant)
    同一个线程在持有锁的情况下,可以再次获取该锁,而不会发生死锁
  • 公平性
    多个线程竞争同一个锁时,这些线程能否按照它们发出请求的顺序获得锁
  • 条件变量
    提供了与锁关联的 Condition 对象,可以用于实现更复杂的线程间协调。

1.可重入性
ReentrantLock 的可重入性体现在同一个线程可以多次获得同一个锁,而不会发生死锁。这是通过内部维护一个持有锁的线程计数器来实现的。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockReentrancyExample {private final Lock lock = new ReentrantLock();public void outerMethod() {lock.lock(); // 第一次获得锁try {innerMethod(); // 在同一线程中调用另一个方法,再次获得锁} finally {lock.unlock(); // 第一次释放锁}}public void innerMethod() {lock.lock(); // 第二次获得锁try {// 执行需要同步的代码块System.out.println("线程 " + Thread.currentThread().getName() + " 获得锁");} finally {lock.unlock(); // 第二次释放锁System.out.println("线程 " + Thread.currentThread().getName() + " 释放锁");}}public static void main(String[] args) {ReentrantLockReentrancyExample example = new ReentrantLockReentrancyExample();// 启动一个线程调用 outerMethod 方法new Thread(() -> {example.outerMethod();}).start();}
}

outerMethod 方法中调用了 innerMethod 方法,而这两个方法都在同一个线程中执行。当线程首次进入 outerMethod 时,它成功获得了锁,并在 innerMethod 中再次成功获得了同一个锁。在 innerMethod 中释放锁时,锁的计数器减为零,才真正释放了锁。这种方式确保了同一线程可以在持有锁的情况下多次进入同一个锁保护的代码块。

我们看下执行流程:

  1. 线程进入outerMethod,获取锁。
  2. 调用innerMethod,在同一线程中再次获取锁。
  3. innerMethod执行完毕后释放锁,但锁仍然保持在outerMethod中。
  4. outerMethod执行完毕后释放锁,此时其他线程有机会获取锁。

什么场景下,会使用到锁的可重入性

  1. 递归调用
    当一个方法递归调用自身,并且这个方法是在持有锁的情况下调用的,可重入性允许同一个线程在递归调用中多次获取相同的锁,而不会发生死锁。
public class RecursiveExample {private final Object lock = new Object();public void recursiveMethod(int count) {synchronized (lock) {if (count > 0) {System.out.println("Count: " + count);recursiveMethod(count - 1); // 递归调用,再次获取相同锁}}}public static void main(String[] args) {RecursiveExample example = new RecursiveExample();example.recursiveMethod(3);}
}
  1. 嵌套调用
    当一个方法调用了另一个方法,而这两个方法都需要获取相同的锁时,可重入性使得同一个线程可以在嵌套调用中多次获取相同的锁。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class NestedCallExample {private final Lock lock = new ReentrantLock();public void outerMethod() {lock.lock(); // 第一次获得锁try {System.out.println("执行 outerMethod");innerMethod(); // 在同一线程中再次获取相同锁} finally {lock.unlock(); // 第一次释放锁}}public void innerMethod() {lock.lock(); // 第二次获得锁try {System.out.println("执行 innerMethod");} finally {lock.unlock(); // 第二次释放锁}}public static void main(String[] args) {NestedCallExample example = new NestedCallExample();example.outerMethod();}
}

二、公平性

  1. 公平锁: 一个公平的锁会按照请求锁的顺序逐个地授予等待的线程,确保所有线程都有机会获得锁,避免饥饿(某个线程一直无法获取锁的情况)
ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
  1. 非公平锁: 在一个非公平的锁中,当锁可用时,系统会任意选择一个等待的线程赋予锁,而不考虑等待的时间或请求的顺序。这可能导致某些线程一直无法获得锁,从而引发饥饿问题
ReentrantLock unfairLock = new ReentrantLock(false); // 非公平锁

需要注意的是,虽然公平锁确保了锁的公平性,但在高并发环境下,公平锁的性能可能相对较低,因为每次都要考虑等待队列中线程的顺序。非公平锁可能会在性能上有一些优势,但可能导致某些线程长时间无法获得锁。

在实际应用中,一般情况下会使用非公平锁,因为在高并发的情况下,公平锁可能会导致线程频繁切换,影响性能。非公平锁虽然在一些情况下可能会引入不公平的竞争,但能够更好地提高并发性能。选择使用公平锁还是非公平锁需要根据具体的业务场景和性能需求来权衡。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class FairnessExample {private static final int THREAD_COUNT = 5;private static final Lock fairLock = new ReentrantLock(true);  // 公平锁private static final Lock unfairLock = new ReentrantLock(false); // 非公平锁private static void performTask(Lock lock, String lockType) {for (int i = 0; i < 3; i++) {lock.lock();try {System.out.println("Thread " + Thread.currentThread().getName() +" acquired " + lockType + " lock, counter: " + i);} finally {lock.unlock();}}}public static void main(String[] args) {// 使用公平锁for (int i = 0; i < THREAD_COUNT; i++) {new Thread(() -> performTask(fairLock, "fair")).start();}// 使用非公平锁for (int i = 0; i < THREAD_COUNT; i++) {new Thread(() -> performTask(unfairLock, "unfair")).start();}}
}

在上述示例中,创建了两个 ReentrantLock,一个是公平锁,一个是非公平锁。在 performTask 方法中,线程通过 lock() 方法获取锁,执行一些操作,然后通过 unlock() 方法释放锁。运行这个程序,你会观察到使用公平锁时,线程按照请求锁的顺序获取锁,而使用非公平锁时,线程可能会插队成功,不按照请求的顺序获取锁。这是通过 ReentrantLock 的公平性来体现的。

1.2 ReentrantLock比synchronized的优点(难度:★★★ 频率:★★)

1.可中断性

可中断性是指在一个线程等待获取锁的过程中,如果其他线程对该等待线程进行中断(调用 interrupt() 方法),那么等待线程能够感知到中断,并有机会响应中断而不是一直等待下去。在这种情况下,等待线程会收到 InterruptedException 异常。

在使用 ReentrantLock 的 lockInterruptibly() 方法时,线程可以响应中断,即在等待锁的过程中,如果线程被其他线程中断,它会立即抛出 InterruptedException 异常,而不是一直等待。

下面是一个简单的示例,演示了 ReentrantLock 的可中断性:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockInterruptExample {private static final Lock lock = new ReentrantLock();public static void main(String[] args) {Thread thread1 = new Thread(() -> {try {lock.lockInterruptibly(); // 可中断获取锁try {System.out.println("Thread 1 acquired the lock");Thread.sleep(2000); // 模拟持有锁的一些操作} finally {lock.unlock();}} catch (InterruptedException e) {System.out.println("Thread 1 interrupted while waiting for the lock");}});Thread thread2 = new Thread(() -> {try {lock.lockInterruptibly(); // 可中断获取锁try {System.out.println("Thread 2 acquired the lock");} finally {lock.unlock();}} catch (InterruptedException e) {System.out.println("Thread 2 interrupted while waiting for the lock");}});// 启动第一个线程,并让它持有锁thread1.start();// 等待一段时间,确保第一个线程先获取到锁try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// 启动第二个线程,但在获取锁之前中断它thread2.start();thread2.interrupt();}
}结果输出:
Thread 1 acquired the lock
Thread 2 interrupted while waiting for the lock

第二个线程在获取锁之前被中断, 当中断时抛出InterruptedException, 从而可以在中断的处理代码块中执行相应的逻辑。

2.超时获取
ReentrantLock提供了一种超时获取锁的方式,即通过 tryLock(long time, TimeUnit unit) 方法,线程在一定的时间范围内尝试获取锁,如果在指定的时间内获取到锁,则返回 true,否则返回 false。这样可以避免线程一直阻塞等待锁,而是在一定时间内尝试获取,如果获取不到则可以执行其他逻辑或放弃锁的获取。

方法的参数 time 表示等待时间的数量,unit 表示等待时间的单位。如果在指定的时间内获取到锁,方法返回 true,否则返回 false。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;public class ReentrantLockTimeoutExample {private static final Lock lock = new ReentrantLock();public static void main(String[] args) {Thread thread = new Thread(() -> {try {if (lock.tryLock(2, TimeUnit.SECONDS)) { // 尝试在2秒内获取锁try {System.out.println("Thread acquired the lock");} finally {lock.unlock();}} else {System.out.println("Thread failed to acquire the lock within 2 seconds");}} catch (InterruptedException e) {System.out.println("Thread interrupted while waiting for the lock");}});// 启动线程thread.start();// 等待一段时间后中断线程try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt(); // 中断线程}
}

在上述示例中,一个线程尝试在2秒内获取锁,如果在2秒内获取到锁,则执行相应的逻辑,否则放弃锁的获取。在等待的过程中,另一个线程对该线程进行中断。在中断的情况下,tryLock 方法会抛出 InterruptedException 异常,并在异常处理代码块中执行相应的逻辑。这就是 ReentrantLock 的超时获取。

3.条件变量
ReentrantLock 提供了与锁关联的条件变量(Condition),条件变量允许线程以灵活的方式进行等待和通知,以实现更复杂的线程协作。条件变量提供了一种在某些条件不满足时线程等待的机制,并在条件满足时通知其他线程的方式。

要使用 ReentrantLock 的条件变量,首先需要通过 ReentrantLock 的 newCondition() 方法创建一个条件变量。然后,可以使用条件变量的 await() 方法让线程等待条件满足,以及使用 signal() 或 signalAll() 方法通知其他等待的线程条件已经满足。

下面是一个简单的示例,演示了 ReentrantLock 的条件变量的基本用法:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ConditionExample {private final Lock lock = new ReentrantLock();private final Condition condition = lock.newCondition();private boolean isConditionMet = false;public void awaitCondition() throws InterruptedException {lock.lock();try {while (!isConditionMet) {// 等待条件满足condition.await();}// 执行条件满足后的操作System.out.println("Condition is met!");} finally {lock.unlock();}}public void signalCondition() {lock.lock();try {// 改变条件isConditionMet = true;// 通知等待的线程条件已满足condition.signal();} finally {lock.unlock();}}public static void main(String[] args) {ConditionExample example = new ConditionExample();// 启动一个线程等待条件new Thread(() -> {try {example.awaitCondition();} catch (InterruptedException e) {e.printStackTrace();}}).start();// 主线程改变条件并通知等待的线程example.signalCondition();}
}

在这个例子中,awaitCondition 方法用于等待条件满足,而 signalCondition 方法用于改变条件并通知等待的线程。在使用条件变量时,通常需要在获取锁后使用 await 方法等待条件,而在满足条件时使用 signal 或 signalAll 方法通知等待的线程。条件变量的使用有助于实现更灵活的线程协作。

condition.await()会阻塞线程运行吗?
是的,condition.await()方法会阻塞当前线程的执行。在 ReentrantLock 中,await() 方法用于使当前线程等待,并释放当前线程持有的锁,直到其他线程调用相应的 signal() 或 signalAll() 方法,或者被中断,或者超时,才会继续执行。

具体来说,在 await() 被调用时,它会释放当前线程持有的锁,使其他线程有机会获取这个锁。当条件满足时,通过调用 signal() 或 signalAll() 来唤醒一个或所有等待的线程。被唤醒的线程会尝试重新获得锁,然后继续执行。

awaitCondition 方法中的 condition.await() 会使调用该方法的线程等待,直到其他线程调用 signalCondition 方法,将条件设置为满足,并唤醒等待的线程。

需要注意的是,在使用 await() 之前,必须先获得与 Condition 相关联的锁,否则会抛出 IllegalMonitorStateException。在 await() 期间,线程会释放锁,以便其他线程可以进入相应的临界区。

isConditionMet并没有使用voliate, 在线程中是怎么感知它的值变成true
虽然确实没有使用 volatile 关键字来声明 isConditionMet 变量,但是它是在同一个锁的保护下被读取和修改的。

在Java中,当一个线程在获取锁的时候,会从主内存中读取共享变量的最新值,并在执行过程中将其缓存在线程的本地内存中。其他线程在获取同一把锁时,会从主内存中重新读取共享变量的值。因为 ReentrantLock 是一个可重入锁,同一个线程在获取锁的时候,不会真正释放锁,因此它的本地内存中的共享变量值是可见的。

在你的例子中,awaitCondition 方法中的 while (!isConditionMet) 中的读取操作和 signalCondition 方法中的写入操作都在同一个 ReentrantLock 的保护下,这确保了线程在获取锁的时候能够看到最新的共享变量值。

虽然没有使用 volatile,但由于所有对 isConditionMet 的读取和写入都在同一把锁的保护下,因此在这个特定的上下文中,是可以保证可见性的。要注意的是,如果 isConditionMet 不是在同一个锁的保护下进行读写,或者在其他地方可能会涉及到多线程并发访问,那么使用 volatile 或其他同步手段可能是更安全的选择。

1.3 CAS的原理和优缺点

CAS,Compare And Swap(比较并交换),是一种多线程同步的原子操作, 用于实现多线程环境下的数据共享.

CAS操作包含三个参数

  1. 内存地址: 需要进行原子操作的内存地址
  2. 期望值: 预期内存位置的当前值, 可以理解为更新前的值, 用于比较
  3. 新值

1.原理:

  1. 读取内存值: CAS首先读取内存地址的当前值, 这个值通常称为期望值
  2. 执行操作: CAS执行相应的操作, 例如给期望值赋值, 或者其他复杂的操作, 得到新值
  3. 比较值: CAS比较期望值与当前内存地址的实际值是否相等, 如果相等, 说明在读取和执行操作的过程中, 没有其他线程修改了这个值
  4. 更新值: 比较成功后, CAS将新值写回到内存位置, 如果在这个过程中,其他线程修改了内存位置的值,CAS会失败。
  5. 检查CAS的结果: CAS操作通常返回一个布尔值,指示操作是否成功。如果操作成功,表示CAS过程中没有其他线程干扰,如果失败,则可能需要重新尝试整个CAS过程, 直到CAS操作成功, 或达到某个预定的重试次数

2.缺点:

  1. 循环时间长, 开销大: CAS 操作需要通过循环来不断尝试更新变量的值,直到成功。在高并发情况下,可能需要多次尝试才能成功,导致循环时间较长,增加了开销。
  2. ABA 问题: CAS 操作本质上是比较并交换,但它不会关心变量的值在比较前后是否发生了其他变化。这可能导致ABA问题,即一个值在经过一系列操作后又变回原始值,但 CAS 操作无法察觉到这种变化

1.4 synchronized与Lock的区别(难度:★★ 频率:★★★★)

synchronizedLock
实现方式Java 内置的关键字是一个接口
锁的获取方式使用关键字修饰的同步代码块或方法在进入时会自动获取锁,在退出时自动释放锁。如果发生异常,锁也会被释放需要手动调用 Lock 接口的 lock() 方法获取锁,使用 unlock() 方法释放锁。通常使用 try-finally 语句确保在获取锁后最终会释放锁,以处理异常情况。
可中断性不支持中断。如果一个线程在获取锁的过程中被中断,它会一直等待锁的释放。支持中断。线程可以在等待锁的过程中响应中断,从而提高了对中断的响应性
公平性不保证公平性。线程争夺锁的顺序是不确定的,可能导致某些线程一直无法获取锁。可以选择是否公平。ReentrantLock 的构造方法可以传入一个参数,用于指定锁是否为公平锁,默认为非公平锁。
条件变量内置的 wait() 和 notify() 方法用于支持条件等待和通知。Lock 接口提供了显式的条件变量,可以使用 newCondition() 方法创建条件对象,并使用 await()、signal() 和 signalAll() 方法进行等待和通知

1.5 常用的原子类有哪些, 它们是如何保证原子性的?

  • 基本类型
    • AtomicBoolean
    • AtomicInteger
    • AtomicLong
  • 引用类型
    • AtomicReference
    • AtomicStampedReference
    • AtomicReferenceFieldUpdater
    • AtomicMarkableReference
  • 数组类型
    • AtomicIntegerArray
    • AtomicLongArray
    • AtomicReferenceArray
  • 字段类型
    • AtomicIntegerFieldUpdater
    • AtomicLongFieldUpdater
    • AtomicStampedFieldUpdater
  • JDK8新增原子类简介
    • DoubleAccumulator
    • LongAccumulator
    • DoubleAdder
    • LongAdder

原子类的实现通常使用CAS操作

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

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

相关文章

快猫视频模板源码定制开发 苹果CMS 可打包成双端APP

苹果CMS快猫视频网站模板源码&#xff0c;可用于开发双端APP&#xff0c;后台支持自定义参数&#xff0c;包括会员升级页面、视频、演员、专题、收藏和会员系统等完整模块。还可以直接指定某个分类下的视频为免费专区&#xff0c;具备完善的卡密支付体系&#xff0c;无需人工管…

Git 中 rebase、reset、revert 有什么区别?

在Git中&#xff0c;rebase、reset和revert是三个常用的操作命令&#xff0c;它们用于处理合并分支、回退版本、撤销更改。 区别&#xff1a; 1、rebase&#xff08;变基&#xff09;&#xff1a;git rebase命令用于将一个分支的提交应用到另一个分支上&#xff0c;从而重新组…

听GPT 讲Rust源代码--src/tools(17)

File: rust/src/tools/rust-analyzer/crates/profile/src/hprof.rs 在Rust源代码中&#xff0c;rust/src/tools/rust-analyzer/crates/profile/src/hprof.rs文件是rust-analyzer中的性能分析模块&#xff0c;用于代码运行时的性能统计和分析。下面将详细介绍每个结构体的作用&a…

【操作系统】什么是进程?

文章目录 进程进程的属性进程的状态挂起 进程 进程是一个可并发执行的具有独立功能的程序关于某个数据集合的执行过程&#xff0c;也是操作系统进行资源分配和保护的基本单位。 进程的属性 结构性&#xff1a; 共享性&#xff1a;同一程序运行于不同数据集合上构成不同的进程…

Flink Table API 与 SQL 编程整理

Flink API总共分为4层这里主要整理Table API的使用 Table API是流处理和批处理通用的关系型API&#xff0c;Table API可以基于流输入或者批输入来运行而不需要进行任何修改。Table API是SQL语言的超集并专门为Apache Flink设计的&#xff0c;Table API是Scala和Java语言集成式…

一文学会 Apache Zeppelin

Zeppelin资料 Zeppelin项目信息 Zeppelin官网 http://zeppelin.apache.org/Zeppelin源码地址 https://github.com/apache/zeppelinZeppelin JIRA: https://issues.apache.org/jira/projects/ZEPPELIN/summaryZeppelin文档 Flink on Zeppelin 文档集中地 https://www.yuque.co…

176.【2023年华为OD机试真题(C卷)】整数对最小和(贪心算法(Greedy Algorithm)实现JavaPythonC++JS)

🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 【2023年华为OD机试真题(C卷)】整数对最小和(遍历和条件判断实现Java&Python&C++&&JS)题目描述解题思路题解代码Python题…

【漏洞复现】奥威亚 教学视频应用服务平台任意文件上传漏洞

漏洞描述 AVA 教学视频应用服务平台是由广州市奥威亚电子科技有限公司基于当前教育视频资源建设的背景及用户需求的调研,开发出来能够适应时代发展和满足学校需求,具有实效性、多功能、特点鲜明的平台。 该平台存在任意文件上传漏洞,通过此漏洞攻击者可上传webshell木马,…

Promise.all()和Promise.race()

参考文章 Promise.all() Promise.all()方法用于将多个 Promise 实例&#xff0c;包装成一个新的 Promise 实例。 const p Promise.all([p1, p2, p3]);上面代码中&#xff0c;Promise.all()方法接受一个数组作为参数&#xff0c;p1、p2、p3都是 Promise 实例&#xff0c;如果…

【DP】62.不同路径

题目 法1&#xff1a;二维DP 必须掌握&#xff01; class Solution {public int uniquePaths(int m, int n) {int[][] matrix new int[m][n];Arrays.fill(matrix[0], 1);for (int i 0; i < m; i) {matrix[i][0] 1;}for (int i 1; i < m; i) {for (int j 1; j <…

OpenCV-9颜色空间的转换

颜色转换API&#xff1a;cvtColor&#xff08;img&#xff0c;colorsapce&#xff09; cvt含义为转换 convesion(转换) 下面为示例代码&#xff1a; import cv2# callback中至少有一个参数 def callback(value):passcv2.namedWindow("color", cv2.WINDOW_NORMAL) …

C#上位机与欧姆龙PLC的通信03----创建项目工程

1、创建仿真PLC 这是一款CP1H-X40DR-A的PLC&#xff0c;呆会后面创建工程的时候需要与这个类型的PLC类型一致&#xff0c;否则程序下载不到PLC上。 2、创建虚拟串口 首先安装&#xff0c;这个用来创建虚拟串口来模拟真实的串口&#xff0c;也就是上位机上有那种COM口&#xf…

Java版直播商城免 费 搭 建:电商、小程序、三级分销及免 费 搭 建,平台规划与营销策略全掌握

随着互联网的快速发展&#xff0c;越来越多的企业开始注重数字化转型&#xff0c;以提升自身的竞争力和运营效率。在这个背景下&#xff0c;鸿鹄云商SAAS云产品应运而生&#xff0c;为企业提供了一种简单、高效、安全的数字化解决方案。 鸿鹄云商SAAS云产品是一种基于云计算的软…

神经科学与计算神经科学的蓬勃发展与未来趋势

导言 神经科学和计算神经科学是当前科学研究领域中备受关注的方向。本文将深入研究这两个领域的发展历程、遇到的问题、解决过程&#xff0c;以及未来的可用范围。我们还将关注在各国的应用现状以及未来的研究趋势&#xff0c;探讨如何在竞争中取胜&#xff0c;以及在哪些方面发…

、|| 运算符能做什么?

1、&& 运算符也叫逻辑与 &#xff08;1&#xff09;在表达式中&#xff1a;先找到第一个虚值表达式并返回它&#xff0c;如果没有找到任何虚值表达式&#xff0c;则返回最后一个真值表达式 &#xff08;2&#xff09;采用短路来防止不必要的工作 console.log(false …

阿里云大模型数据存储解决方案,为 AI 创新提供推动力

云布道师 随着国内首批大模型产品获批名单问世&#xff0c;百“模”大战悄然开启。在这场百“模”大战中&#xff0c;每一款大模型产品的诞生&#xff0c;都离不开数据的支撑。如何有效存储、管理和处理海量多模态数据集&#xff0c;并提升模型训练、推理的效率&#xff0c;保…

LVS+keepalived小白都看得懂也不来看?

1 高可用集群 1.1 一个合格的集群应该具备的特性 1.负载均衡 LVS Nginx HAProxy F5 2.健康检查&#xff08;使得调度器检查节点状态是否可以正常运行&#xff0c;调度器&#xff08;负载均衡器&#xff09;也要做健康检查&#xff09;for调度器/节点服务器 keeplived hearb…

微服务常见的配置中心简介

微服务架构中&#xff0c;常见的配置中心包括以下几种&#xff1a; Spring Cloud Config&#xff1a; Spring Cloud Config是官方推荐的配置中心解决方案&#xff0c;它支持将配置文件存储在Git、SVN等版本控制系统中。通过提供RESTful API&#xff0c;各个微服务可以远程获取和…

机器学习中的一些经典理论定理

PAC学习理论 当使用机器学习方法来解决某个特定问题时&#xff0c;通常靠经验或者多次试验来选择合适的模型、训练样本数量以及学习算法收敛的速度等。但是经验判断或多次试验往往成本比较高&#xff0c;也不太可靠&#xff0c;因此希望有一套理论能够分析问题难度、计算模型能…

PyQt6 QTableWidget表格控件

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计50条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版…