Java面试黄金宝典6
1. 什么是 CAS
- 原理:
- CAS (Compare-And-Swap)是一种硬件级别的原子操作指令,在 Java 并发编程中常被用于实现无锁算法。其核心逻辑是:在进行数据更新时,会先将内存位置
V的值与预期原值A进行比较,如果二者相等,就把内存位置V的值更新为新值B;若不相等,则说明在这期间有其他线程对该内存位置的值进行了修改,此时不会执行更新操作。 - 在 Java 里,
sun.misc.Unsafe类提供了对 CAS 操作的支持。不过,Unsafe类的使用具有一定的风险性,所以 Java 又在java.util.concurrent.atomic包下提供了一系列基于 CAS 实现的原子类,像AtomicInteger、AtomicLong等。
- CAS (Compare-And-Swap)是一种硬件级别的原子操作指令,在 Java 并发编程中常被用于实现无锁算法。其核心逻辑是:在进行数据更新时,会先将内存位置
- 要点:
- 原子性:CAS 操作由硬件指令直接保障其原子性,在执行过程中不会被其他线程中断,能有效避免多线程环境下的数据竞争问题。
- 无锁机制:与传统的加锁机制不同,CAS 操作无需加锁,这样就避免了线程阻塞和上下文切换带来的开销,从而提升了并发性能。
- ABA 问题:这是 CAS 操作面临的主要问题。当一个值从
A变为B后又变回A时,CAS 操作会认为值没有发生改变,进而继续执行更新操作,然而实际上该值已经经历了变化。
- 应用:
- 解决 ABA 问题:可以借助带有时间戳的原子引用
AtomicStampedReference来解决 ABA 问题。AtomicStampedReference不仅会比较值是否相等,还会比较时间戳是否一致,只有当值和时间戳都匹配时才会执行更新操作。 - 应用场景:CAS 广泛应用于并发容器、原子类以及一些无锁算法的实现中,例如 Java 中的
ConcurrentHashMap在部分操作上就运用了 CAS 来保证并发安全。
- 解决 ABA 问题:可以借助带有时间戳的原子引用
2. 什么是可重入锁 ReentrantLock
- 原理:
ReentrantLock是java.util.concurrent.locks包下的一个类,它实现了Lock接口,是一种可重入的互斥锁。可重入意味着同一个线程能够多次获取同一把锁而不会被阻塞。每获取一次锁,锁的内部计数器就会加 1;每释放一次锁,计数器就会减 1。当计数器的值变为 0 时,锁才会被完全释放。ReentrantLock内部通过AbstractQueuedSynchronizer(AQS)来实现锁的状态管理和线程的排队等待。
- 要点:
- 手动锁管理:与
synchronized不同,ReentrantLock需要手动调用lock()方法来获取锁,调用unlock()方法来释放锁,通常要在finally块中调用unlock()以确保锁一定会被释放。 - 灵活性:
ReentrantLock提供了更多的灵活性,比如可以选择实现公平锁或非公平锁,还支持中断锁等待、限时锁等待等功能。 - 条件变量:
ReentrantLock可以配合Condition对象使用,实现更精细的线程间通信和同步。
- 手动锁管理:与
- 应用:
- 公平锁和非公平锁的选择:公平锁能够保证线程获取锁的公平性,但会增加线程上下文切换的开销;非公平锁虽然可能导致某些线程长时间得不到锁,但可以提高系统的吞吐量。在实际应用中,需要根据具体的业务场景来选择合适的锁类型。
- 与
synchronized的性能比较:在竞争不激烈的情况下,synchronized和ReentrantLock的性能相差不大;但在竞争激烈的场景下,ReentrantLock的性能可能会更优。
3. 什么是乐观锁和悲观锁,阻塞锁,自旋锁,偏向锁,轻量锁,重量锁,公平锁,非公平锁,有哪些区别
- 乐观锁和悲观锁
- 原理:
- 乐观锁:它假定数据在大多数情况下不会发生冲突,所以在操作数据时不会加锁,而是在更新数据时检查数据是否被其他线程修改过。通常是通过版本号或时间戳等机制来实现。
- 悲观锁:它假定数据很容易发生冲突,因此在操作数据之前会先加锁,防止其他线程访问,确保在自己操作数据期间数据不会被其他线程修改。
- 区别:
- 适用场景:乐观锁适用于读多写少的场景,因为在这种场景下数据发生冲突的概率较低,使用乐观锁可以减少加锁和解锁的开销;悲观锁适用于写多读少的场景,因为在这种场景下数据发生冲突的概率较高,使用悲观锁可以保证数据的一致性。
- 性能:乐观锁的开销较小,因为它不需要加锁和解锁的操作;悲观锁的开销较大,因为它需要进行加锁和解锁操作,并且可能会导致线程阻塞和上下文切换。
- 原理:
- 阻塞锁和自旋锁
- 原理:
- 阻塞锁:当一个线程获取不到锁时,会被阻塞进入等待状态,直到锁被释放。此时线程会让出 CPU 资源,进入睡眠状态,等待其他线程释放锁后再被唤醒。
- 自旋锁:当一个线程获取不到锁时,不会进入阻塞状态,而是不断地循环尝试获取锁,在这个过程中线程会一直占用 CPU 资源。
- 区别:
- CPU 资源占用:阻塞锁会让出 CPU 资源,不会一直占用 CPU;自旋锁会一直占用 CPU 资源,直到获取到锁或达到自旋的最大次数。
- 适用场景:阻塞锁适用于锁的持有时间较长的场景,因为在这种情况下线程阻塞等待可以避免 CPU 资源的浪费;自旋锁适用于锁的持有时间较短的场景,因为在这种情况下线程不断自旋尝试获取锁的开销相对较小。
- 原理:
- 偏向锁、轻量锁和重量锁
- 原理:
- 偏向锁:在只有一个线程访问同步块时,会将锁偏向该线程。当该线程再次进入同步块时,无需进行任何同步操作,直接进入同步块执行代码,这样可以减少加锁和解锁的开销。
- 轻量锁:当有多个线程交替访问同步块时,会使用轻量锁。轻量锁通过 CAS 操作来获取和释放锁,避免了使用操作系统的互斥量,从而减少了线程阻塞和上下文切换的开销。
- 重量锁:当多个线程同时竞争锁时,轻量锁会升级为重量锁。重量锁使用操作系统的互斥量来实现同步,会导致线程阻塞和上下文切换,开销较大。
- 区别:
- 适用场景:偏向锁适用于单线程场景,开销最小;轻量锁适用于多线程交替访问场景,开销较小;重量锁适用于多线程同时竞争场景,开销最大。
- 锁的升级:锁的状态会根据线程的竞争情况进行升级,即从偏向锁升级为轻量锁,再升级为重量锁,但锁的状态不会降级。
- 原理:
- 公平锁和非公平锁
- 原理:
- 公平锁:多个线程按照申请锁的顺序来获取锁,先到先得。当一个线程释放锁后,会从等待队列中选择最早申请锁的线程来获取锁。
- 非公平锁:多个线程获取锁的顺序是不确定的,可能后申请的线程先获取到锁。当一个线程释放锁后,任何一个等待的线程都有机会获取锁。
- 区别:
- 公平性:公平锁可以保证线程获取锁的公平性,避免某些线程长时间得不到锁;非公平锁可能会导致某些线程长时间得不到锁。
- 性能:公平锁会增加线程上下文切换的开销,因为每次释放锁后都需要从等待队列中选择下一个线程;非公平锁可以提高系统的吞吐量,因为它减少了线程上下文切换的次数。
- 原理:
4. 什么是 ReentrantLock 和 synchronized,有什么区别
- 原理:
- synchronized:它是 Java 中的关键字,是一种内置的锁机制。当
synchronized修饰实例方法时,使用的是对象锁;当修饰静态方法时,使用的是类锁;当修饰代码块时,需要指定锁对象。synchronized会在进入同步块或同步方法时自动获取锁,在退出时自动释放锁。 - ReentrantLock:它是 Java 中的一个类,实现了
Lock接口,是一种可重入的互斥锁。通过调用lock()方法来获取锁,调用unlock()方法来释放锁。
- synchronized:它是 Java 中的关键字,是一种内置的锁机制。当
- 区别
- 锁的获取和释放方式:
synchronized是自动获取和释放锁,由 Java 虚拟机负责管理锁的生命周期,使用起来比较简单。ReentrantLock需要手动获取和释放锁,使用时需要在finally块中调用unlock()方法,以确保锁一定会被释放,否则可能会导致死锁。
- 锁的灵活性:
synchronized是一种比较简单的锁机制,缺乏灵活性,只能实现非公平锁,并且不支持中断锁等待和限时锁等待等功能。ReentrantLock提供了更多的灵活性,可以选择实现公平锁或非公平锁,支持中断锁等待、限时锁等待等功能,还可以配合Condition对象实现更精细的线程间通信和同步。
- 性能:
- 在竞争不激烈的情况下,
synchronized和ReentrantLock的性能相差不大,因为 Java 虚拟机对synchronized进行了很多优化,如偏向锁、轻量锁等。 - 在竞争激烈的情况下,
ReentrantLock的性能可能会更好,因为它可以根据具体的业务场景选择合适的锁类型,并且可以避免一些不必要的线程阻塞和上下文切换。
- 在竞争不激烈的情况下,
- 锁的获取和释放方式:
5. 重入锁、对象锁、类锁的关系
- 重入锁:
- 重入锁指的是同一个线程能够多次获取同一把锁而不会被阻塞。
ReentrantLock和synchronized都是可重入锁。当一个线程第一次获取锁时,锁的计数器会加 1,之后该线程再次获取同一把锁时,计数器会继续加 1;每次释放锁时,计数器会减 1,当计数器为 0 时,锁才会被完全释放。
- 重入锁指的是同一个线程能够多次获取同一把锁而不会被阻塞。
- 对象锁:
- 当
synchronized修饰实例方法或代码块时使用的是对象锁。同一时刻只有一个线程可以访问该对象的被synchronized修饰的方法或代码块。不同的对象实例拥有各自独立的对象锁,一个线程可以同时获取多个不同对象的对象锁。
- 当
- 类锁:
- 当
synchronized修饰静态方法或代码块时使用的是类锁。类锁是基于类的Class对象实现的,同一时刻只有一个线程可以访问该类的被synchronized修饰的静态方法或代码块。所有该类的对象实例共享同一个类锁。
- 当
- 关系:
- 对象锁和类锁都是基于重入锁的机制实现的,它们的区别在于锁的范围不同。对象锁是针对对象实例的,不同的对象实例可以同时执行被
synchronized修饰的实例方法或代码块;类锁是针对类的,所有该类的对象实例都需要竞争同一个类锁。
- 对象锁和类锁都是基于重入锁的机制实现的,它们的区别在于锁的范围不同。对象锁是针对对象实例的,不同的对象实例可以同时执行被
6. 如何创建线程?哪种好?
- 创建线程的方式
- 继承
Thread类:- 创建一个类继承
Thread类,并重写run()方法,run()方法中包含了线程要执行的代码。然后创建该类的实例并调用start()方法启动线程。
- 创建一个类继承
- 继承
java
class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread is running");}
}public class Main {public static void main(String[] args) {MyThread thread = new MyThread();thread.start();}
}
- 实现
Runnable接口:- 创建一个类实现
Runnable接口,实现run()方法。然后创建该类的实例并将其作为参数传递给Thread类的构造函数,最后调用start()方法启动线程。
- 创建一个类实现
java
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Thread is running");}
}public class Main {public static void main(String[] args) {MyRunnable runnable = new MyRunnable();Thread thread = new Thread(runnable);thread.start();}
}
- 实现
Callable接口:- 创建一个类实现
Callable接口,实现call()方法,call()方法可以有返回值。然后使用FutureTask类将Callable对象包装起来,再将FutureTask对象作为参数传递给Thread类的构造函数,最后调用start()方法启动线程。可以通过FutureTask的get()方法获取call()方法的返回值。
- 创建一个类实现
java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {return 1 + 2;}
}public class Main {public static void main(String[] args) throws Exception {MyCallable callable = new MyCallable();FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread thread = new Thread(futureTask);thread.start();System.out.println(futureTask.get());}
}
- 哪种好:
- 实现
Runnable接口和Callable接口的方式更好。因为 Java 是单继承的,继承Thread类会限制类的扩展性,一个类一旦继承了Thread类,就不能再继承其他类了。而实现Runnable接口和Callable接口可以让类继承其他类,同时还能实现多线程功能。此外,实现Runnable接口和Callable接口的方式可以更好地实现资源共享,多个线程可以共享同一个Runnable或Callable对象。
- 实现
7. 线程具体有哪些状态
Java 中的线程有以下六种状态,定义在 Thread.State 枚举中:
- NEW:线程刚被创建,但还没有调用
start()方法。此时线程还没有进入运行状态,只是在 Java 虚拟机中分配了一些内存空间。 - RUNNABLE:线程正在 Java 虚拟机中执行,或者准备执行。它包含了操作系统线程状态中的就绪和运行两种状态。当线程调用
start()方法后,会进入RUNNABLE状态,此时线程可能正在 CPU 上执行,也可能在等待 CPU 资源。 - BLOCKED:线程正在等待获取一个监视器锁,进入同步块或同步方法时被阻塞。当一个线程试图进入一个已经被其他线程占用的同步块或同步方法时,会进入
BLOCKED状态,直到获取到锁为止。 - WAITING:线程处于等待状态,需要其他线程显式地唤醒。例如调用
Object.wait()、Thread.join()或LockSupport.park()方法会使线程进入WAITING状态。在这种状态下,线程会释放持有的锁,直到被其他线程调用Object.notify()、Object.notifyAll()或LockSupport.unpark()方法唤醒。 - TIMED_WAITING:线程处于定时等待状态,在指定的时间后会自动唤醒。例如调用
Thread.sleep(long millis)、Object.wait(long timeout)或LockSupport.parkNanos()等方法会使线程进入TIMED_WAITING状态。在这种状态下,线程也会释放持有的锁,等待指定的时间后会自动唤醒继续执行。 - TERMINATED:线程已经执行完毕,生命周期结束。当线程的
run()方法执行完毕或者抛出未捕获的异常时,线程会进入TERMINATED状态,此时线程占用的资源会被释放。
8. 一般线程和守护线程的区别
- 一般线程:也称为用户线程,是执行用户程序的主要线程。当所有用户线程执行完毕后,Java 虚拟机才会退出。用户线程可以通过继承
Thread类、实现Runnable接口或Callable接口来创建。 - 守护线程:是一种为其他线程提供服务的线程,当所有用户线程执行完毕后,守护线程会自动终止,即使守护线程的任务还没有完成。守护线程通常用于执行一些后台任务,如垃圾回收线程、日志记录线程等。
- 区别:
- 生命周期:用户线程会影响 Java 虚拟机的退出,只有当所有用户线程都执行完毕后,Java 虚拟机才会退出;守护线程不会影响 Java 虚拟机的退出,当所有用户线程执行完毕后,守护线程会自动终止。
- 设置方式:可以通过
Thread.setDaemon(true)方法将一个线程设置为守护线程,但必须在调用start()方法之前设置,否则会抛出IllegalThreadStateException异常。
9. 什么是 sleep wait yield notify notifyAll join,有什么区别
- sleep:
Thread.sleep(long millis)是Thread类的静态方法,用于让当前线程暂停执行指定的时间,线程进入TIMED_WAITING状态。在睡眠期间,线程不会释放对象锁,其他线程无法获取该对象的锁。- 例如:
java
public class SleepExample {public static void main(String[] args) {Thread thread = new Thread(() -> {try {System.out.println("Thread is sleeping");Thread.sleep(2000);System.out.println("Thread wakes up");} catch (InterruptedException e) {e.printStackTrace();}});thread.start();}
}
- wait:
Object.wait()是Object类的方法,用于让当前线程进入等待状态,线程进入WAITING或TIMED_WAITING状态。当调用wait()方法时,线程会释放对象锁,其他线程可以获取该对象的锁。需要其他线程调用notify()或notifyAll()方法来唤醒等待的线程。- 例如:
java
public class WaitExample {public static void main(String[] args) {final Object lock = new Object();Thread thread1 = new Thread(() -> {synchronized (lock) {try {System.out.println("Thread 1 is waiting");lock.wait();System.out.println("Thread 1 wakes up");} catch (InterruptedException e) {e.printStackTrace();}}});Thread thread2 = new Thread(() -> {synchronized (lock) {System.out.println("Thread 2 is notifying");lock.notify();}});thread1.start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}thread2.start();}
}
- yield:
Thread.yield()是Thread类的静态方法,用于让当前线程放弃 CPU 时间片,进入就绪状态,让其他线程有机会执行,但不保证一定会让出 CPU。调用yield()方法后,线程不会释放对象锁。- 例如:
java
public class YieldExample {public static void main(String[] args) {Thread thread1 = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("Thread 1: " + i);Thread.yield();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("Thread 2: " + i);}});thread1.start();thread2.start();}
}
- notify:
Object.notify()是Object类的方法,用于唤醒在此对象监视器上等待的单个线程。如果有多个线程在等待,只会随机唤醒一个线程。
- notifyAll:
Object.notifyAll()是Object类的方法,用于唤醒在此对象监视器上等待的所有线程。被唤醒的线程会竞争对象锁,只有获得锁的线程才能继续执行。
- join:
Thread.join()是Thread类的方法,用于等待调用该方法的线程执行完毕。例如,thread.join()会让当前线程等待thread线程执行完毕后再继续执行。- 例如:
java
public class JoinExample {public static void main(String[] args) {Thread thread = new Thread(() -> {try {System.out.println("Thread is running");Thread.sleep(2000);System.out.println("Thread is finished");} catch (InterruptedException e) {e.printStackTrace();}});thread.start();try {thread.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Main thread continues");}
}
10. 什么是中断线程
中断线程是指一个线程向另一个线程发送中断信号,通知它应该停止执行。在 Java 中,可以通过调用 Thread.interrupt() 方法来中断一个线程。被中断的线程可以通过 Thread.interrupted() 或 Thread.isInterrupted() 方法来检查自己是否被中断。
Thread.interrupt():用于中断线程,设置线程的中断标志位。当调用interrupt()方法时,如果线程处于WAITING、TIMED_WAITING或SLEEPING状态,会抛出InterruptedException异常,并清除中断标志位;如果线程处于其他状态,只会设置中断标志位。Thread.interrupted():是Thread类的静态方法,用于检查当前线程是否被中断,并清除中断标志位。如果当前线程被中断,返回true,否则返回false。Thread.isInterrupted():是Thread类的实例方法,用于检查线程是否被中断,不会清除中断标志位。如果线程被中断,返回true,否则返回false。
需要注意的是,调用 interrupt() 方法并不会立即终止线程,而是给线程一个中断信号,线程可以根据自己的逻辑来处理这个信号。例如,线程可以在捕获到 InterruptedException 异常时进行相应的处理,或者在适当的时机检查中断标志位,根据标志位的值来决定是否退出线程。
java
public class InterruptExample {public static void main(String[] args) {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("Thread is running");try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt(); // 重新设置中断标志位}}System.out.println("Thread is interrupted");});thread.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}thread.interrupt();}
}
在这个例子中,线程会不断检查自己的中断标志位,当主线程调用 thread.interrupt() 方法时,线程会捕获到 InterruptedException 异常,然后重新设置中断标志位,最终退出循环。
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90498450
相关文章:
Java面试黄金宝典6
1. 什么是 CAS 原理: CAS (Compare-And-Swap)是一种硬件级别的原子操作指令,在 Java 并发编程中常被用于实现无锁算法。其核心逻辑是:在进行数据更新时,会先将内存位置 V 的值与预期原值 A 进行比较&#x…...
【深度学习新浪潮】AI ISP技术与手机厂商演进历史
本文是关于AI ISP(人工智能图像信号处理器)的技术解析、与传统ISP(图像信号处理器)的区别、近三年研究进展,以及各大手机厂商在该领域演进历史的详细报告。本报告综合多个权威来源的信息,力求全面、深入地呈现相关技术发展脉络与行业动态。 第一部分:AI ISP的定义及与传…...
C语言基础08
内容提要 数组 排序算法:冒泡排序 二维数组 字符数组 数组 冒泡排序 排序思想(向前冒泡) 一次只排好一个数,针对n个数,最差情况需要n-1次就可以排好 每次排序假定第一个元素是最大或者最小,用第一个…...
基于Arm GNU Toolchain编译生成的.elf转hex/bin文件格式方法
基于Arm GNU Toolchain编译生成的.elf转hex/bin文件格式方法 已经弃用的版本(Version 10.3-2021.10):gcc-arm-none-eabi:https://developer.arm.com/downloads/-/gnu-rmArm GNU Toolchain当前版本:https://developer.a…...
1.angular介绍
初級使用视频添加链接描述 angular工具 angular.module(‘名’, [依赖模块]) 模块 angular.bind(*) : 修改this指向 angualr.copy() // a angular.copy(a, b) —a完全覆盖了b,c就是a angular.extend(a, b) a里面集成了b属性 angular.isArray angular.isDate angular.isDefin…...
java项目40分钟后token失效问题排查(40分钟后刷新页面白屏)
项目40分钟后token失效问题排查(40分钟后刷新页面白屏) 经过我 对比失效前token 可以正常访问接口,失效后的token 不能访问系统, 得出结论,我系统对接第三方 sso 系统,token 失效时间 在他们那边配置&…...
音频进阶学习二十——DFT离散傅里叶变换
文章目录 前言一、FT、FS、DTFT、DFS1.FT和FS2.DTFT和DFS 二、DFT定义1.对于DFT的理解1)DTFT和DFT2)DFS和DFT3)有限长序列和周期序列 2.圆周卷积1)线性卷积2)圆周卷积 三、频率采样和插值恢复1.频率采样的影响2.频率采…...
【Rust】集合的使用——Rust语言基础16
文章目录 1. 前言2. Vector2.1. 构建一个 vector2.2. 获取 vector 中的元素2.3. 遍历 vector2.4. 使用枚举来储存多种类型 3. String3.1. 新建字符串3.2. 更新字符串3.3. 字符串的内部结构3.3.1. 字符串如何访问内部元素?3.3.2. 字节、标量值和字形簇 3.4. 字符串 s…...
centos 7 部署ftp 基于匿名用户
在 CentOS 7 上搭建基于匿名用户的 FTP 服务,可按以下步骤进行: 1. 安装 vsftpd 服务 vsftpd 是一款常用的 FTP 服务器软件,可使用以下命令进行安装: bash sudo yum install -y vsftpd2. 启动并设置开机自启 vsftpd 服务 bash …...
Apache SeaTunnel脚本升级及参数调优实战
最近作者针对实时数仓的Apache SeaTunnel同步链路,完成了双引擎架构升级与全链路参数深度调优,希望本文能够给大家有所启发,欢迎批评指正! Apache SeaTunnel 版本 :2.3.9 Doris版本:2.0.6 MySQL JDBC Conne…...
算法 | 优化算法比较
===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 优化算法 一、主流优化算法分类1、传统梯度类算法2、启发式算…...
破局 MySQL 死锁:深入理解锁机制与高效解决方案
死锁的原理 1. 什么是死锁? 当 多个事务 在并发执行时,每个事务都 持有其他事务需要的锁,同时又在 等待对方释放锁,导致所有事务都无法继续执行的状态,称为 死锁(Deadlock)。 2. 死锁的四个必要…...
学习记录-cssjs-综合复习案例(二)
目录 商城复合案例功能实现(二)商城首页实现步骤1.准备工作2. 搭建html框架3. 编写js代码 完整实例代码完整项目心得 商城复合案例功能实现(二) 使用html,css,基于bootstrap框架以及媒体查询搭建响应式布局…...
使用 JDBC 插入数据并获取自动生成的主键(如 MySQL 的 AUTO_INCREMENT 或 Oracle 的序列) 的完整示例代码,包含详细注释
以下是使用 JDBC 插入数据并获取自动生成的主键(如 MySQL 的 AUTO_INCREMENT 或 Oracle 的序列) 的完整示例代码,包含详细注释: import java.sql.*;public class GeneratedKeysExample {// 数据库连接参数private static final St…...
图解AUTOSAR_CP_EEPROM_Abstraction
AUTOSAR EEPROM抽象模块详细说明 基于AUTOSAR标准的EEPROM抽象层技术解析 目录 1. 概述 1.1 核心功能1.2 模块地位2. 架构概览 2.1 架构层次2.2 模块交互3. 配置结构 3.1 主要配置容器3.2 关键配置参数4. 状态管理 4.1 基本状态4.2 状态转换5. 接口设计 5.1 主要接口分类5.2 接…...
汇川EASY系列之以太网通讯(MODBUS_TCP做从站)
汇川easy系列PLC做MODBUS_TCP从站,不需要任何操作,但是有一些需要知道的东西。具体如下: 1、汇川easy系列PLC做MODBUS_TCP从站,,ModbusTCP服务器默认开启,无需设置通信协议(即不需要配置),端口号为“502”。ModbusTCP从站最多支持31个ModbusTCP客户端(ModbusTCP主站…...
QT 图表(拆线图,栏状图,饼状图 ,动态图表)
效果 折线图 // 创建折线数据系列// 创建折线系列QLineSeries *series new QLineSeries;// series->append(0, 6);// series->append(2, 4);// series->append(3, 8);// 创建图表并添加系列QChart *chart new QChart;chart->addSeries(series);chart->setTit…...
基于vue框架的在线影院系统a079l(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
系统程序文件列表 项目功能:用户,电影,电影类别,电影库 开题报告内容 基于Vue框架的在线影院系统开题报告 一、研究背景与意义 随着文化娱乐产业的蓬勃发展,电影院作为人们休闲消遣的重要场所,其管理效率和服务质量直接影响着顾客的观影体…...
vscode/cursor中python运行路径设置 模块导入问题
vscode/cursor中python运行路径设置 ## 文件路径设置 问题描述 pycharm的项目用cursor运行,出现目录找不到 后来利用 os.getcwd(),经过打印调试发现是IDE的本身配置问题 pycharm中,os.getcwd()默认打开当前脚本所在目录 vscode/cursor中…...
OpenCV图像拼接(1)概述
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 此图说明了在Stitcher类中实现的拼接模块流程。使用该类,可以配置/移除某些步骤,即根据特定需求调整拼接流程。流程中的所…...
NFS 安装与测试
NFS 安装与测试 服务器 # NFS 共享目录 mkdir -p ${HOME}/Share/nfs && sudo chown -R nobody:nogroup ${HOME}/Share/nfs# 安装 NFS Server sudo apt install nfs-kernel-server# 配置 NFS 目录 sudo cp -arf /etc/exports /etc/exports.bak sudo tee -a /etc/exports…...
深度学习与传统算法在人脸识别领域的演进:从Eigenfaces到ArcFace
一、传统人脸识别方法的发展与局限 1.1 Eigenfaces:主成分分析的经典实践 算法原理 Eigenfaces是基于主成分分析(PCA)的里程碑式方法。其核心思想是将人脸图像视为高维向量,通过协方差矩阵计算特征向量(即特征脸&…...
基于ssm学科竞赛小程序的设计及实现(源码+lw+部署文档+讲解),源码可白嫖!
摘要 随着信息时代的来临,过去的学科竞赛管理方式的缺点逐渐暴露,本次对过去的学科竞赛管理方式的缺点进行分析,采取计算机方式构建学科竞赛小程序。本文通过阅读相关文献,研究国内外相关技术,提出了一种关于竞赛信息…...
【嵌入式学习】触发器 - ADC - DAC
# 触发器 基本概念:一种能够存储一位二进制信息的数字逻辑电路,其输出不仅取决于当前输入,还与之前的状态有关。 常见触发器类型: ①RS触发器:最基本的双稳态电路,包含两个输入(置位S和复位R&…...
[特殊字符][特殊字符][特殊字符][特殊字符][特殊字符][特殊字符]壁紙 流光染墨,碎影入梦
#Cosplay #🧚♀️Bangni邦尼🐰. #📷 穹妹 Set.01 #后期圈小程序 琼枝低垂,霜花浸透夜色,风起时,微光轻拂檐角,洒落一地星辉。远山隐于烟岚,唯余一抹青黛,勾勒出天光水…...
虚拟机的三种 Linux 网络配置原理图解读
前言 虚拟机的网络连接方式主要有 三种模式:桥接模式(Bridged)、NAT 模式(Network Address Translation)、仅主机模式(Host-Only)。每种模式都有不同的使用场景和网络适应性,具体解释…...
AI Agent系列(七) -思维链(Chain of Thought,CoT)
AI Agent系列【七】 前言一、CoT技术详解1.1 CoT组成1.2 CoT的特点 二、CoT的作用三、CoT的好处四、CoT适用场景五、CoT的推理结构 前言 思维链(Chain of Thought,CoT),思维链就是一系列中间的推理步骤(a series of intermediate reasoning steps),通过…...
SpringBoot实现异步调用的方法
在Java中使用Spring Boot实现异步请求和异步调用是一个常见的需求,可以提高应用程序的性能和响应能力。以下是实现这两种异步操作的基本方法: 一、异步请求(Asynchronous Request) 异步请求允许客户端发送请求后立即返回&#x…...
PurpleLlama大模型安全全套检测方案
1. 引入 PurpleLlama是Meta的大模型安全整体解决方案(参考1),它包括了 (1)安全评估 CyberSecEval是一个用于评估大型语言模型(LLMs)安全风险的基准套件,其目标是解决随着 LLMs 的广…...
vue el-table 设置selection选中状态
toggleRowSelection 方法 vue el-table 设置selection选中状态 关键代码 multipleTableRef.value!.toggleRowSelection(item, true);<el-table:data"data":border"setBorder"v-bind"$attrs"row-key"id"stripestyle"width: 1…...
