Java 并发编程封神!从入门到精通,面试再也不怕被问爆

news2026/4/4 18:30:11
目录synchronized 支持重入吗如何实现的?syncronized锁升级的过程讲一下JVM对Synchornized的优化介绍一下AQSCAS 和 AQS 有什么关系如何用 AQS 实现一个可重入的公平锁Threadlocal作用原理具体里面存的key value是啥会有什么问题如何解决?悲观锁和乐观锁的区别Java中想实现一个乐观锁都有哪些方式CAS 有什么缺点为什么不能所有的锁都用CASCAS 有什么问题Java是怎么解决的voliatle关键字有什么作用指令重排序的原理是什么volatile可以保证线程安全吗volatile和sychronized比较什么是公平锁和非公平锁非公平锁吞吐量为什么比公平锁大Synchronized是公平锁吗ReentrantLock是怎么实现公平锁的什么情况会产生死锁问题如何解决线程池介绍一下线程池的工作原理线程池的参数有哪些线程池工作队列满了有哪些拒接策略有线程池参数设置的经验吗核心线程数设置为0可不可以线程池种类有哪些线程池一般是怎么用的线程池中shutdown ()shutdownNow()这两个方法有什么作用提交给线程池中的任务可以被撤回吗场景多线程打印奇偶数怎么控制打印的顺序单例模型既然已经用了synchronized为什么还要在加volatile3个线程并发执行1个线程等待这三个线程全部执行完在执行怎么实现假设两个线程并发读写同一个整型变量初始值为零每个线程加 50 次结果可能是什么synchronized 支持重入吗如何实现的?synchronized是基于原子性的内部锁机制是可重入的因此在一个线程调用synchronized方法的同时在其方法体内部调用该对象另一个synchronized方法也就是说一个线程得到一个对象锁后再次请求该对象锁是允许的这就是synchronized的可重入性。synchronized底层是利用计算机系统mutex Lock实现的。每一个可重入锁都会关联一个线程ID和一个锁状态status。当一个线程请求方法时会去检查锁状态。如果锁状态是0代表该锁没有被占用使用CAS操作获取锁将线程ID替换成自己的线程ID。如果锁状态不是0代表有线程在访问该方法。此时如果线程ID是自己的线程ID如果是可重入锁会将status自增1然后获取到该锁进而执行相应的方法如果是非重入锁就会进入阻塞队列等待。在释放锁时如果是可重入锁的每一次退出方法就会将status减1直至status的值为0最后释放该锁。如果非可重入锁的线程退出方法直接就会释放该锁syncronized锁升级的过程讲一下无锁-偏向锁-轻量级锁-重量级锁。对象刚创建时对象头的Mark Word为无锁状态无线程关联。当我们第一个线程获取该锁的时候就会升级成偏向锁第一次通过cas方式将线程id放到对象头mark word中修改成功就获取该锁后续该线程再次获取锁时不用cas方式只需检查Mark Word的线程ID是否相等——是则直接获取锁第二个线程尝试获取该锁Mark Word的线程ID不是当前线程id偏向锁失效,升级为轻量级锁,线程通过CAS操作将Mark Word替换为自己的锁记录指针,成功就获取轻量级锁失败了自旋若自旋达到上限仍未获取锁轻量级锁升级为重量级锁未获取锁的线程进入操作系统阻塞队列后续通过操作系统互斥量竞争锁。JVM对Synchornized的优化锁膨胀锁升级synchronized 从无锁升级到偏向锁再到轻量级锁最后到重量级锁的过程它叫做锁膨胀也叫做锁升级。JDK 1.6 之前synchronized 是重量级锁也就是说 synchronized 在释放和获取锁时都会从用户态转换成内核态而转换的效率是比较低的。但有了锁膨胀机制之后synchronized 的状态就多了无锁、偏向锁以及轻量级锁了这时候在进行并发操作时大部分的场景都不需要用户态到内核态的转换了这样就大幅的提升了 synchronized 的性能。锁消除JVM 虚拟机如果检测到这段代码的锁只有当前线程能用没有任何其他线程会碰就会将这段代码所属的同步锁消除掉从而到底提高程序性能的目的。锁粗化将多个连续的加锁、解锁操作连接在一起扩展成一个范围更大的锁就是多次小锁”合并成“一次大锁”减少“锁操作的次数”•自适应自旋锁指通过自身循环尝试获取锁的一种方式优点在于它避免一些线程的挂起和恢复操作因为挂起线程和恢复线程都需要从用户态转入内核态这个过程是比较慢的所以通过自旋的方式可以一定程度上避免线程挂起和恢复所造成的性能开销。介绍一下AQSAQS的话其实就一个jdk提供的类AbstractQueuedSynchronizer抽象队列同步器是阻塞式锁和相关的同步器工具的框架。内部有一个属性 state 属性来表示资源的状态默认state等于0表示没有获取锁state等于1的时候才标明获取到了锁。通过cas 机制设置 state 状态在它的内部还提供了基于 FIFO 的等待队列是一个双向列表其中tail 指向队列最后一个元素head 指向队列中最久的一个元素其中我们刚刚聊的ReentrantLock底层的实现就是一个AQS。CAS 和 AQS 有什么关系CAS 和 AQS 两者的区别• CAS 是一种乐观锁机制它包含三个操作数内存位置V、预期值A和新值B。CAS 操作的逻辑是如果内存位置 V 的值等于预期值 A则将其更新为新值 B否则不做任何操作。整个过程是原子性的。• AQS 是一个用于构建锁和同步器的框架许多同步器如 ReentrantLock、Semaphore、CountDownLatch 等都是基于 AQS 构建的。AQS 使用一个 volatile 的整数变量 state 来表示同步状态通过内置的 FIFO 队列来管理等待线程。它提供了一些基本的操作如 acquire获取资源和 release释放资源这些操作会修改 state 的值并根据 state 的值来判断线程是否可以获取或释放资源。AQS 的 acquire 操作通常会先尝试获取资源如果失败线程将被添加到等待队列中并阻塞等待。release 操作会释放资源并唤醒等待队列中的线程。CAS 和 AQS 两者的联系• CAS 为 AQS 提供原子操作支持AQS 内部使用 CAS 操作来更新 state 变量以实现线程安全的状态修改。在 acquire 操作中当线程尝试获取资源时会使用 CAS 操作尝试将 state 从一个值更新为另一个值如果更新失败说明资源已被占用线程会进入等待队列。在 release 操作中当线程释放资源时也会使用 CAS 操作将 state 恢复到相应的值以保证状态更新的原子性。如何用 AQS 实现一个可重入的公平锁继承 AbstractQueuedSynchronizer实现可重入逻辑检查当前线程是否已经持有锁如果是则增加锁的持有次数通过 state 变量如果不是尝试使用 CAS操作来获取锁。实现公平性按照队列顺序来获取锁创建锁的外部类创建一个外部类内部持有 AbstractQueuedSynchronizer 的子类对象并提供 lock 和 unlock 方法进行获取锁和释放锁。Threadlocal作用原理具体里面存的key value是啥会有什么问题如何解决?面试官谈谈你对ThreadLocal的理解候选人嗯是这样的~~ThreadLocal 主要功能有两个第一个是可以实现资源对象的线程隔离让每个线程各用各的资源对象避免争用引发的线程安全问题第二个是实现了线程内的资源共享面试官好的那你知道ThreadLocal的底层原理实现吗候选人嗯知道一些~在ThreadLocal内部维护了一个一个 ThreadLocalMap 类型的成员变量用来存储资源对象当我们调用 set 方法就是以 ThreadLocal 自己作为 key资源对象作为 value放入当前线程的 ThreadLocalMap 集合中当调用 get 方法就是以 ThreadLocal 自己作为 key到当前线程中查找关联的资源值当调用 remove 方法就是以 ThreadLocal 自己作为 key移除当前线程关联的资源值面试官好的那关于ThreadLocal会导致内存溢出这个事情了解吗候选人嗯我之前看过源码我想一下~~是因为ThreadLocalMap 中的 key 被设计为弱引用它是被动的被GC调用释放key不过关键的是只有key可以得到内存释放而value不会因为value是一个强引用。在使用ThreadLocal 时都把它作为静态变量即强引用因此无法被动依靠 GC 回收建议主动的remove 释放 key这样就能避免内存溢出。悲观锁和乐观锁的区别乐观锁的思想最乐观的估计不一定的线程来修改共享变量它在操作共享数据时不先加锁而是直接读取/修改数据操作完成后通过某种机制如版本号、CAS验证数据是否被其他线程修改过。若未被修改则提交若被修改则重试悲观锁的思想最悲观的估计一定会有其它线程来修改共享变量操作共享数据前先主动加锁确保在操作期间其他线程无法修改数据从而避免数据竞争。Java中想实现一个乐观锁都有哪些方式CASCompare and Swap操作版本号控制增加一个版本号字段记录数据更新时候的版本每次更新时递增版本号。在更新数据时同时比较版本号若当前版本号和更新前获取的版本号一致则更新成功否则失败。时间戳在更新数据时在比较时间戳。如果当前时间戳大于数据的时间戳则说明数据已经被其他线程更新更新失败CAS 有什么缺点ABA问题ABA的问题指的是在CAS更新的过程中逻辑是“当前值是否等于预期旧值”但如果数据被修改为其他值后又改回原值如A→B→ACAS会误以为“数据未被修改”导致操作错误。Java中有AtomicStampedReference来解决这个问题加入了预期标志和更新后标志两个字段更新时不光检查值还要检查当前的标志是否等于预期标志全部相等的话才会更新。循环时间长开销大自旋CAS的方式如果长时间不成功会给CPU带来很大的开销。只能保证一个共享变量的原子操作只对一个共享变量操作可以保证原子性但是多个则不行多个可以通过AtomicReference来处理或者使用锁synchronized实现为什么不能所有的锁都用CASCAS操作是基于循环重试的机制如果CAS操作一直未能成功线程会一直自旋重试占用CPU资源。在高并发情况下大量线程自旋会导致CPU资源浪费。CAS 有什么问题Java是怎么解决的CAS 操作中增加版本号Stamp或标记每次修改都更新版本号使验证时不仅检查值还要检查版本号是否匹配。voliatle关键字有什么作用保证变量对所有线程的可见性。禁止指令重排序优化volatile关键字在Java中主要通过内存屏障来禁止特定类型的指令重排序指令重排序的原理是什么在执行程序时为了提高性能处理器和编译器常常会对指令进行重排序但是重排序要满足下面 2 个条件才能进行• 在单线程环境下不能改变程序运行的结果• 存在数据依赖关系的不允许重排序。volatile可以保证线程安全吗volatile关键字可以保证可见性但不能保证原子性因此不能完全保证线程安全。volatile关键字用于修饰变量当一个线程修改了volatile修饰的变量的值其他线程能够立即看到最新的值从而避免了线程之间的数据不一致。但是volatile并不能解决多线程并发下的复合操作问题比如i这种操作不是原子操作如果多个线程同时对i进行自增操作volatile不能保证线程安全。对于复合操作需要使用synchronized关键字或者Lock来保证原子性和线程安全。volatile和sychronized比较Synchronized解决了多线程访问共享资源时可能出现的竞态条件和数据不一致的问题保证了线程安全性。Volatile解决了变量在多线程环境下的可见性和有序性问题确保了变量的修改对其他线程是可见的。Synchronized: Synchronized是一种排他性的同步机制保证了多个线程访问共享资源时的互斥性即同一时刻只允许一个线程访问共享资源Volatile: Volatile是一种轻量级的同步机制用来保证变量的可见性和禁止指令重排序。什么是公平锁和非公平锁公平锁 指多个线程按照申请锁的顺序来获取锁线程直接进入队列中排队队列中的第一个线程才能获得锁。优点在于各个线程公平平等每个线程等待一段时间后都有执行的机会缺点就在于整体执行速度更慢吞吐量更小。非公平锁多个线程加锁时直接尝试获取锁能抢到锁到直接占有锁抢不到才会到等待队列的队尾等待。优点就在于整体执行速度更快吞吐量更大缺点同时也可能产生线程饥饿问题也就是说如果一直有线程插队那么在等待队列中的线程可能长时间得不到运行。非公平锁吞吐量为什么比公平锁大公平锁执行流程获取锁时先将线程自己添加到等待队列的队尾并休眠当某线程用完锁之后会去唤醒等待队列中队首的线程尝试去获取锁锁的使用顺序也就是队列中的先后顺序在整个过程中线程会从运行状态切换到休眠状态再从休眠状态恢复成运行状态但线程每次休眠和恢复都需要从用户态转换成内核态而这个状态的转换是比较慢的所以公平锁的执行速度会比较慢。非公平锁执行流程当线程获取锁时会先通过 CAS 尝试获取锁如果获取成功就直接拥有锁如果获取锁失败才会进入等待队列等待下次尝试获取锁。这样做的好处是获取锁不用遵循先到先得的规则从而避免了线程休眠和恢复的操作这样就加速了程序的执行效率。Synchronized是公平锁吗Synchronized不属于公平锁ReentrantLock是公平锁。ReentrantLock是怎么实现公平锁的ReentrantLock公平锁与非公平锁的 lock() 方法唯一的区别就在于公平锁在获取锁时多了一个限制条件hasQueuedPredecessors() 为 false。公平锁和非公平锁的核心区别如果是公平锁那么一旦已经有线程在排队了当前线程就不再尝试获取锁对于非公平锁而言无论是否已经有线程在排队都会尝试获取一下锁获取不到的话再去排队。tryLock() 方法它不遵守设定的公平原则。线程执行 tryLock() 方法的时候一旦有线程释放了锁那么这个正在 tryLock 的线程就能获取到锁即使设置的是公平锁模式就是tryLock 可以插队。底层调用的就是nonfairTryAcquire()表明了是不公平的。什么情况会产生死锁问题如何解决死锁只有同时满足以下四个条件才会发生互斥条件互斥条件是指多个线程不能同时使用同一个资源。持有并等待条件持有并等待条件是指当线程 A 已经持有了资源 1又想申请资源 2而资源 2 已经被线程 C 持有了所以线程 A 就会处于等待状态但是线程 A 在等待资源 2 的同时并不会释放自己已经持有的资源 1。不可剥夺条件不可剥夺条件是指当线程已经持有了资源在自己使用完之前不能被其他线程获取线程 B 如果也想使用此资源则只能在线程 A 使用完并释放后才能获取。环路等待条件环路等待条件指的是在死锁发生的时候两个线程获取资源的顺序构成了环形链避免死锁问题就只需要破环其中一个条件就可以线程池介绍一下线程池的工作原理线程池是为了减少频繁的创建线程和销毁线程带来的性能损耗线程池分为核心线程池线程池的最大容量还有等待任务的队列提交一个任务如果核心线程没有满就创建核心线程执行如果满了就是会加入等待队列如果等待队列满了判断是否达到最大线程数量若没有就会创建空闲线程执行如果都达到最大线程数量就会按照丢弃策略进行处理。线程池的参数有哪些corePoolSize线程池核心线程数量。maximumPoolSize限制了线程池能创建的最大线程总数包括核心keepAliveTime空闲时间当线程池中线程的数量大于corePoolSize并且某个线程的空闲时间超过了 keepAliveTime那么这个线程就会被销毁。unit空闲时间的单位。workQueue工作队列。threadFactory线程工厂。用来给线程取名字。handler拒绝策略。线程池工作队列满了有哪些拒接策略常用的四种拒绝策略包括CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy1.AbortPolicy直接抛出异常默认策略2.CallerRunsPolicy用调用者所在的线程来执行任务3.DiscardOldestPolicy丢弃阻塞队列中靠最前的任务并执行当前任务4.DiscardPolicy直接丢弃任务有线程池参数设置的经验吗参考回答① 高并发、任务执行时间短 -- CPU核数1 减少线程上下文的切换② 并发不高、任务执行时间长IO密集型的任务 -- (CPU核数 * 2 1)计算密集型任务 -- CPU核数1 ③ 并发高、业务执行时间长解决这种类型任务的关键不在于线程池而在于整体架构的设计看看这些业务里面某些数据是否能做缓存是第一步增加服务器是第二步至于线程池的设置设置参考2核心线程数设置为0可不可以可以当核心线程数为0的时候会创建一个非核心线程进行执行。当核心线程数为 0 时来了一个任务之后会先将任务添加到任务队列同时也会判断当前工作的线程数是否为 0如果为 0则会创建空闲线程来执行任务。线程池种类有哪些参考回答在jdk中默认提供了4种方式创建线程池第一个是newCachedThreadPool创建一个可缓存线程池如果线程池长度超过处理需要可灵活回 收空闲线程若无可回收则新建线程。第二个是newFixedThreadPool 创建一个定长线程池可控制线程最大并发数超出的线程会在队列 中等待。第三个是newScheduledThreadPool可以执行延迟任务的线程池支持定时及周期性任务执行。第四个是newSingleThreadExecutor 创建一个单线程化的线程池单例的线程池它只会用唯一的工作线程来执行任 务保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。线程池一般是怎么用的资源风险应该手动 new ThreadPoolExecutor 来创建线程池Executors的快捷方法如newFixedThreadPool的无界队列、newCachedThreadPool的无限扩线程易导致内存溢出OOM可控性手动new ThreadPoolExecutor可自定义核心参数核心/最大线程数、有界队列、拒绝策略适配业务场景可观测性需为线程池命名方便排查问题建议监控队列积压、线程数膨胀等状态提前预警风险。线程池中shutdown ()shutdownNow()这两个方法有什么作用shutdown()置SHUTDOWN状态执行中任务继续不再接受新任务加任务会抛RejectedExecutionException。shutdownNow()置STOP状态中断所有正在执行的线程用Thread.interrupt()丢弃队列待执行任务并返回未执行任务列表但因线程可能不响应中断如无sleep/wait未必立即退出。提交给线程池中的任务可以被撤回吗提交给线程池的任务可以撤回核心通过Future.cancel(boolean mayInterruptIfRunning)实现未开始的任务直接取消不会执行正在执行的任务若mayInterruptIfRunningtrue调用Thread.interrupt()尝试中断需任务响应中断如含sleep()/wait()否则无法停止若mayInterruptIfRunningfalse不中断任务继续执行完已完成的任务取消无效。场景多线程打印奇偶数怎么控制打印的顺序利用wait()和notify()来控制线程的执行顺序。public class PrintOddEven { private static final Object lock new Object(); private static int count 1; private static final int MAX_COUNT 10; public static void main(String[] args) { Runnable printOdd () - { synchronized (lock) { while (count MAX_COUNT) { if (count % 2 ! 0) { System.out.println(Thread.currentThread().getName() : count); lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Runnable printEven () - { synchronized (lock) { while (count MAX_COUNT) { if (count % 2 0) { System.out.println(Thread.currentThread().getName() : count); lock.notify(); } else { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } }; Thread oddThread new Thread(printOdd, OddThread); Thread evenThread new Thread(printEven, EvenThread); oddThread.start(); evenThread.start(); } }单例模型既然已经用了synchronized为什么还要在加volatilepublic class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }volatile 确保了对象引用的可见性和创建过程的有序性避免了由于指令重排序而导致的错误。instance new Singleton(); 这行代码并不是一个原子操作它实际上可以分解为以下几个步骤• 分配内存空间。• 实例化对象。• 将对象引用赋值给 instance。没有 volatile 的情况下可能会出现重排序例如先将对象引用赋值给 instance但对象的实例化操作尚未完成。这样其他线程在检查 instance null 时会认为单例已经创建从而得到一个未完全初始化的对象导致错误。3个线程并发执行1个线程等待这三个线程全部执行完在执行怎么实现可以使用 CountDownLatch 来实现 3 个线程并发执行另一个线程等待这三个线程全部执行完再执行的需求。以下是具体的实现步骤• 创建一个 CountDownLatch 对象并将计数器初始化为 3因为有 3 个线程需要等待。• 创建 3 个并发执行的线程在每个线程的任务结束时调用 countDown 方法将计数器减 1。• 创建第 4 个线程使用 await 方法等待计数器为 0即等待其他 3 个线程完成任务。import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) { // 创建一个 CountDownLatch初始计数为 3 CountDownLatch latch new CountDownLatch(3); // 创建并启动 3 个并发线程 for (int i 0; i 3; i) { final int threadNumber i 1; new Thread(() - { try { System.out.println(Thread threadNumber is working.); // 模拟线程执行任务 Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread threadNumber has finished.); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 任务完成后计数器减 1 latch.countDown(); } }).start(); } // 创建并启动第 4 个线程等待其他 3 个线程完成 new Thread(() - { try { System.out.println(Waiting for other threads to finish.); // 等待计数器为 0 latch.await(); System.out.println(All threads have finished, this thread starts to work.); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } }假设两个线程并发读写同一个整型变量初始值为零每个线程加 50 次结果可能是什么在没有任何同步机制的情况下两个线程并发对同一个整型变量进行 50 次加 1 操作最终结果可能是 100也可能小于 100最坏的结果是 50也就是最终的结果可能是在 [50, 100] 。小于 100 情况的分析由于对整型变量的 num 操作不是原子操作它实际上包含了三个步骤读取变量的值、将值加 1、将新值写回变量。在多线程环境下可能会出现线程安全问题。例如线程 1 和线程 2 同时读取了变量的当前值然后各自将其加 1最后都将相同的新值写回变量这就导致了一次加 1 操作的丢失。这种情况会多次发生最终结果就会小于 100。import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerAddition { private static AtomicInteger num new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { Thread thread1 new Thread(() - { for (int i 0; i 50; i) { num.incrementAndGet(); } }); Thread thread2 new Thread(() - { for (int i 0; i 50; i) { num.incrementAndGet(); } }); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(最终结果: num.get()); } }解决方式通过 synchronized 关键字或 ReentrantLock 确保操作的互斥性。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…