Java面试黄金宝典2
1. 什么是 Concurrent 包
java.util.concurrent
(简称 Concurrent 包)是 Java 5 引入的一个用于并发编程的工具包。它提供了一系列用于处理多线程编程的类和接口,帮助开发者更方便、安全地进行并发编程。
-
原理
该包基于 Java 的多线程机制和锁机制,采用了诸如 CAS(Compare - And - Swap)、AQS(AbstractQueuedSynchronizer)等底层技术。
- CAS:是一种无锁算法,其核心思想是先比较内存中的值是否和预期值一致,如果一致则将新值更新到内存中,这个操作是原子性的。例如,在
AtomicInteger
类中,就使用了 CAS 来实现原子的自增操作。在多线程环境下,多个线程同时尝试修改一个AtomicInteger
的值时,只有一个线程能够成功,其他线程会不断重试,避免了传统锁带来的线程阻塞和上下文切换开销。 - AQS:是一个用于构建锁和同步器的框架,许多并发工具类都基于它实现。AQS 内部维护了一个 FIFO 队列,用于管理等待获取锁的线程。当一个线程尝试获取锁失败时,会被放入队列中阻塞等待;当持有锁的线程释放锁时,会从队列中唤醒一个等待的线程。
- 要点
- 线程池:
ThreadPoolExecutor
:是线程池的核心实现类,开发者可以通过它灵活地配置线程池的参数,如核心线程数、最大线程数、线程空闲时间等。例如,在一个 Web 服务器中,可以根据请求的并发量来调整线程池的大小,提高系统的处理能力。ScheduledThreadPoolExecutor
:用于执行定时任务和周期性任务。它可以在指定的时间点执行任务,或者按照一定的周期重复执行任务,适用于定时数据备份、定时任务调度等场景。
- 并发集合:
ConcurrentHashMap
:在多线程环境下是线程安全的哈希表。它采用分段锁(Java 7 及以前)或 CAS + synchronized(Java 8 及以后)的方式来保证并发操作的安全性,避免了传统HashMap
在并发访问时可能出现的数据不一致问题,如死循环和数据丢失。CopyOnWriteArrayList
:是一个线程安全的动态数组。它的写操作(如add
、remove
等)会创建一个新的数组副本,将原数组中的元素复制到新数组中,并在新数组上进行修改,最后将引用指向新数组。读操作则直接在原数组上进行,不需要加锁,因此在读多写少的场景下性能较好。
- 同步工具类:
CountDownLatch
:用于协调多个线程的执行顺序。它通过一个计数器来实现,主线程可以等待计数器的值减为 0 后再继续执行。例如,在一个多线程的任务中,主线程需要等待所有子线程完成任务后再进行汇总操作,就可以使用CountDownLatch
。CyclicBarrier
:可以让一组线程在到达某个屏障点时进行同步。当所有线程都到达屏障点后,屏障会打开,所有线程可以继续执行。它可以重复使用,适用于多个线程需要反复进行同步的场景。Semaphore
:用于控制对有限资源的访问权限。它通过一个许可证计数器来实现,线程在访问资源前需要获取许可证,访问完后释放许可证。例如,在一个数据库连接池中,可以使用Semaphore
来控制同时使用的连接数。
- 应用
在高并发的 Web 应用中,使用 ConcurrentHashMap
可以替代传统的 HashMap
,避免在多线程环境下出现死循环和数据丢失的问题。线程池可以根据业务需求调整线程数量,提高系统的吞吐量。例如,在电商系统的促销活动期间,并发访问量会大幅增加,可以适当增加线程池的最大线程数,以应对高并发请求。
2. 什么是面向对象,有哪 4 种特性
面向对象编程(OOP)是一种编程范式,它将数据和操作数据的方法封装在一起,形成对象。通过对象之间的交互来完成程序的功能。
- 原理
面向对象的核心思想是将现实世界中的事物抽象成对象,每个对象都有自己的属性和行为。对象之间通过消息传递来进行交互,从而实现程序的功能。例如,在一个汽车模拟程序中,汽车可以抽象成一个对象,它有颜色、型号等属性,还有启动、加速、刹车等行为。不同的汽车对象之间可以通过消息传递来模拟交通场景。
- 要点
- 封装:
- 定义:将数据和操作数据的方法捆绑在一起,隐藏对象的内部实现细节,只对外提供必要的接口。通过访问修饰符(如
private
、protected
、public
)来控制对类成员的访问,提高了代码的安全性和可维护性。 - 示例:在一个银行账户类中,账户余额是一个敏感数据,应该被封装起来。可以将余额属性设置为
private
,并提供getBalance
和deposit
、withdraw
等方法来访问和修改余额,这样可以避免外部代码直接修改余额,保证数据的安全性。
- 定义:将数据和操作数据的方法捆绑在一起,隐藏对象的内部实现细节,只对外提供必要的接口。通过访问修饰符(如
- 继承:
- 定义:子类可以继承父类的属性和方法,从而实现代码的复用。Java 只支持单继承,即一个子类只能有一个直接父类,但可以实现多个接口。子类可以对父类的方法进行重写,以实现自己的功能。
- 示例:在一个动物类层次结构中,狗类可以继承动物类的属性和方法,同时可以重写动物类的
makeSound
方法,实现狗叫的功能。
- 多态:
- 定义:同一个行为具有多个不同表现形式或形态的能力。通过继承和接口实现,父类引用可以指向子类对象,在运行时根据实际对象类型调用相应的方法,提高了代码的灵活性和可扩展性。
- 示例:在一个图形绘制程序中,有一个抽象的图形类,以及圆形、矩形等具体的图形子类。可以定义一个绘制图形的方法,接收一个图形类的引用作为参数,在方法内部根据实际传入的对象类型调用相应的绘制方法,实现多态。
- 抽象:
- 定义:将一类对象的共同特征总结出来,形成抽象类或接口。抽象类不能实例化,它可以包含抽象方法,子类必须实现这些抽象方法。接口是一种特殊的抽象类,只包含抽象方法和常量。
- 示例:在一个交通工具系统中,可以定义一个抽象的交通工具类,包含抽象的移动方法。不同的交通工具子类(如汽车、飞机等)需要实现这个移动方法,以实现自己的移动方式。
- 应用
在大型项目开发中,面向对象的编程思想可以使代码结构更加清晰,易于维护和扩展。例如,在游戏开发中,可以将不同的角色抽象成类,通过继承和多态实现不同角色的不同行为。在软件开发中,使用设计模式(如单例模式、工厂模式等)也是基于面向对象的思想,进一步提高代码的可维护性和可扩展性。
3. 什么是 String、StringBuffer、StringBuilder、hashCode、equals,有什么区别
- String:是不可变的字符序列。一旦创建,其内容不能被修改。每次对
String
对象进行修改时,实际上是创建了一个新的String
对象。 - StringBuffer:是可变的字符序列,线程安全。它的方法大多是同步的,因此在多线程环境下可以安全使用,但性能相对较低。
- StringBuilder:也是可变的字符序列,非线程安全。它的方法没有进行同步处理,因此在单线程环境下性能比
StringBuffer
高。 - hashCode:是
Object
类的一个方法,用于返回对象的哈希码。哈希码是一个整数,通常用于哈希表(如HashMap
、HashSet
)中,提高查找效率。 - equals:是
Object
类的一个方法,用于比较两个对象是否相等。默认情况下,比较的是对象的引用是否相等,子类可以重写该方法来实现自定义的相等比较逻辑。
- 原理
- String:类内部使用
final char[]
数组来存储字符序列,由于final
修饰,数组的引用不能被修改,因此String
是不可变的。当对String
进行拼接操作时,会创建一个新的String
对象,原对象的内容不会改变。 - StringBuffer 和 StringBuilder:内部使用可变的字符数组来存储字符序列,通过
append
、insert
等方法可以修改字符序列。StringBuffer
的方法使用了synchronized
关键字进行同步,保证了线程安全;StringBuilder
没有进行同步处理,因此性能更高。 - hashCode:方法根据对象的内容计算哈希码,不同的对象可能有相同的哈希码,但相同的对象哈希码一定相同。在
String
类中,哈希码的计算是基于字符串的内容,因此相同内容的String
对象哈希码相同。 - equals:方法在
String
类中被重写,用于比较两个字符串的内容是否相等。它会遍历两个字符串的每个字符,只有当所有字符都相等时,才认为两个字符串相等。
- 要点
- 性能方面:在单线程环境下,频繁修改字符序列时,
StringBuilder
性能最好;在多线程环境下,使用StringBuffer
更安全。例如,在一个单线程的字符串拼接任务中,使用StringBuilder
可以显著提高性能;而在一个多线程的日志记录系统中,使用StringBuffer
可以保证数据的一致性。 - 不可变性:
String
的不可变性使得它在字符串常量池等场景中非常有用,可以提高内存的使用效率。字符串常量池是 JVM 中的一块特殊区域,用于存储常量字符串。当创建一个常量字符串时,JVM 会先在常量池中查找是否已经存在相同内容的字符串,如果存在则直接返回引用,避免了重复创建对象。 - 哈希码和相等比较:在使用哈希表时,需要确保对象的
hashCode
和equals
方法的实现是一致的,即如果两个对象equals
比较结果为true
,那么它们的hashCode
必须相同。否则,会导致哈希表的查找和插入操作出现错误。
- 应用
在处理大量字符串拼接时,如果是单线程环境,优先使用 StringBuilder
;如果是多线程环境,则使用 StringBuffer
。在自定义类中,为了能正确使用哈希表,需要重写 hashCode
和 equals
方法。例如,在一个自定义的用户类中,用户的 id
是唯一标识,那么在重写 hashCode
和 equals
方法时,应该基于 id
来进行计算和比较。
4. 什么是文件读取,如何实现
文件读取是指从文件系统中读取文件的内容到程序中进行处理。在 Java 中,可以使用不同的类和方法来实现文件读取。
- 原理
Java 通过输入流(InputStream
和 Reader
)来实现文件读取。输入流是一个抽象概念,它表示从数据源(如文件、网络等)读取数据的通道。InputStream
是字节输入流的基类,用于以字节为单位读取数据;Reader
是字符输入流的基类,用于以字符为单位读取数据。
- 要点
- 字节流:
FileInputStream
用于以字节为单位读取文件,适用于读取二进制文件(如图片、视频等)。它直接从文件中读取字节数据,不会对数据进行任何编码转换。 - 字符流:
FileReader
用于以字符为单位读取文件,适用于读取文本文件。它会根据系统默认的字符编码将字节数据转换为字符数据。为了指定特定的字符编码,可以使用InputStreamReader
包装FileInputStream
。 - 缓冲流:
BufferedInputStream
和BufferedReader
可以提高文件读取的效率,它们内部有一个缓冲区,减少了与磁盘的交互次数。当调用读取方法时,会先从缓冲区中读取数据,如果缓冲区中没有数据,则从文件中读取一批数据到缓冲区中。
- 实现示例
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;public class FileReadingExample {public static void main(String[] args) {try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {e.printStackTrace();}}
}
- 应用
可以使用 RandomAccessFile
类实现随机文件读取,即可以在文件的任意位置进行读写操作。RandomAccessFile
内部维护了一个文件指针,可以通过 seek
方法移动指针的位置,然后进行读写操作。在处理大文件时,可以采用分块读取的方式,避免一次性将整个文件加载到内存中。例如,可以每次读取固定大小的字节块,处理完后再读取下一块。
5. 什么是反射,如何实现
反射是 Java 的一种机制,它允许程序在运行时获取类的信息(如类的属性、方法、构造函数等),并可以动态地创建对象、调用方法、访问属性等。
- 原理
Java 的反射机制基于 Class
类和 java.lang.reflect
包中的类。Class
类是 Java 反射的核心,每个类在 JVM 中都有一个对应的 Class
对象,通过这个对象可以获取类的各种信息。java.lang.reflect
包中包含了 Method
、Field
、Constructor
等类,用于表示类的方法、属性和构造函数,可以通过这些类来动态地操作类的成员。
- 要点
- 获取
Class
对象:Class.forName()
:通过类的全限定名来获取Class
对象。这种方式适用于在运行时根据类名动态加载类。类名.class
:在编译时就确定要获取的类,直接通过类名获取Class
对象。这种方式比较简洁,适用于已知类名的情况。对象.getClass()
:通过对象实例获取其对应的Class
对象。这种方式适用于在运行时根据对象获取其类的信息。
- 创建对象:
Class
对象的newInstance()
方法(Java 9 及以后已弃用):该方法会调用类的无参构造函数来创建对象。如果类没有无参构造函数,会抛出异常。Constructor
类的newInstance()
方法:可以通过Class
对象的getConstructor
或getDeclaredConstructor
方法获取构造函数对象,然后调用其newInstance()
方法来创建对象。这种方式可以调用带参数的构造函数。
- 调用方法:通过
Method
类的invoke()
方法来调用对象的方法。需要先通过Class
对象的getMethod
或getDeclaredMethod
方法获取方法对象,然后传入对象实例和方法参数来调用方法。 - 访问属性:通过
Field
类的get()
和set()
方法来访问和修改对象的属性。需要先通过Class
对象的getField
或getDeclaredField
方法获取属性对象,然后传入对象实例来获取或修改属性值。
- 实现示例
java
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;class MyClass {public void printMessage() {System.out.println("Hello, Reflection!");}
}public class ReflectionExample {public static void main(String[] args) throws Exception {// 获取 Class 对象Class<?> clazz = Class.forName("MyClass");// 创建对象Constructor<?> constructor = clazz.getConstructor();Object obj = constructor.newInstance();// 获取方法Method method = clazz.getMethod("printMessage");// 调用方法method.invoke(obj);}
}
- 应用
反射在框架开发中应用广泛,如 Spring 框架通过反射实现依赖注入和 AOP 功能。在 Spring 中,通过反射机制可以动态地创建对象、调用方法和设置属性,实现对象之间的依赖关系。但反射会带来一定的性能开销,因为它需要在运行时进行类的查找和方法的调用,因此在性能敏感的场景中应谨慎使用。
6. 什么是 JDK、NDK、JRE、JNI,有什么区别
- JDK(Java Development Kit):是 Java 开发工具包,它包含了 JRE 和一系列开发工具(如编译器
javac
、调试器jdb
等)。JDK 是开发 Java 程序的基础,提供了编译、运行 Java 程序所需的环境。 - NDK(Native Development Kit):是 Android 提供的一个工具集,用于在 Android 应用中使用 C 和 C++ 代码。通过 NDK,可以将部分性能敏感的代码用 C 或 C++ 实现,提高应用的性能。
- JRE(Java Runtime Environment):是 Java 运行时环境,它包含了 JVM(Java Virtual Machine)和 Java 核心类库。JRE 是运行 Java 程序的最小环境,用户只需要安装 JRE 就可以运行 Java 程序。
- JNI(Java Native Interface):是 Java 提供的一种机制,允许 Java 代码与本地代码(如 C、C++ 代码)进行交互。通过 JNI,可以在 Java 程序中调用本地方法,也可以在本地代码中调用 Java 方法。
- 区别要点
- 功能用途:
- JDK:用于开发 Java 程序,提供了编译、调试、打包等开发工具。
- NDK:用于在 Android 应用中使用本地代码,提高应用的性能,特别是在处理图形、音频、视频等计算密集型任务时。
- JRE:用于运行 Java 程序,用户只需要安装 JRE 就可以运行已编译好的 Java 程序。
- JNI:用于实现 Java 代码和本地代码的交互,使得 Java 程序可以利用本地代码的高性能和丰富的库资源。
- 包含内容:
- JDK:包含 JRE 和开发工具,如编译器
javac
、调试器jdb
、打包工具jar
等。 - NDK:包含一系列用于编译和链接本地代码的工具和库,如 GCC 编译器、Android 系统库等。
- JRE:包含 JVM 和核心类库,如
java.lang
、java.util
等。 - JNI:是 Java 提供的一组接口和规范,没有具体的工具和库,需要开发者根据规范编写代码。
- JDK:包含 JRE 和开发工具,如编译器
- 应用
在开发 Android 应用时,如果需要使用一些性能敏感的算法或调用一些现有的 C/C++ 库,可以使用 NDK 和 JNI 技术。例如,在游戏开发中,可以使用 C++ 实现游戏的物理引擎,然后通过 JNI 在 Java 层调用。在开发 Java 桌面应用或服务器端应用时,只需要安装 JDK 即可进行开发和运行。
7. 什么是 static 和 final,有什么区别
- static:是 Java 的一个关键字,用于修饰类的成员(成员变量、成员方法、代码块)。被
static
修饰的成员属于类,而不属于某个对象。可以通过类名直接访问,不需要创建对象。 - final:也是 Java 的一个关键字,用于修饰类、方法和变量。被
final
修饰的类不能被继承;被final
修饰的方法不能被重写;被final
修饰的变量一旦赋值,就不能再被修改。
- 原理
- static:成员在类加载时就会被分配内存,并且只分配一次,所有对象共享同一个
static
成员。类加载是 JVM 启动时将类的字节码文件加载到内存中的过程,static
成员在这个过程中被初始化。 - final:关键字主要是为了保证数据的不可变性和类、方法的安全性。对于
final
变量,编译器会在编译时进行检查,确保其值不会被修改;对于final
类和方法,编译器会禁止子类继承和重写。
- 要点
- 修饰变量:
static
变量:是类变量,所有对象共享。它可以在类加载时进行初始化,也可以在静态代码块中进行初始化。final
变量:是常量,一旦赋值不能改变。如果是基本数据类型,其值不能被修改;如果是引用类型,其引用不能被修改,但对象的内容可以被修改。static final
修饰的变量:是类常量,通常用于定义全局常量。它在类加载时被初始化,并且只能初始化一次。
- 修饰方法:
static
方法:可以通过类名直接调用,不能使用this
和super
关键字。因为static
方法属于类,而不是对象,this
和super
关键字是与对象相关的。final
方法:不能被重写,主要用于防止子类修改该方法的实现。例如,在一个工具类中,为了保证某些方法的实现不被修改,可以将这些方法声明为final
。
- 修饰类:
static
不能修饰类,但可以修饰内部类。静态内部类属于外部类,而不属于外部类的对象,可以通过外部类名直接访问。final
修饰的类:不能被继承,用于保证类的安全性和完整性。例如,String
类就是一个final
类,防止其他类继承并修改其行为。
- 应用
在工具类中,通常会使用 static
方法,方便直接调用。例如,Math
类中的所有方法都是 static
方法,可以直接通过类名调用。在定义常量时,使用 static final
可以提高代码的可读性和可维护性。在设计框架时,为了防止子类意外修改某些方法的实现,可以将这些方法声明为 final
。
8. 什么是 map、list、set,有什么区别
- Map:是一种键值对的集合,用于存储具有映射关系的数据。每个键是唯一的,一个键对应一个值。常见的实现类有
HashMap
、TreeMap
、LinkedHashMap
等。 - List:是一种有序的集合,允许存储重复的元素。可以通过索引访问元素。常见的实现类有
ArrayList
、LinkedList
等。 - Set:是一种不允许存储重复元素的集合。元素没有特定的顺序。常见的实现类有
HashSet
、TreeSet
、LinkedHashSet
等。
- 原理
- Map:基于哈希表或红黑树实现,通过键的哈希码来快速定位值。
HashMap
基于哈希表实现,通过哈希函数将键映射到哈希表的某个位置;TreeMap
基于红黑树实现,键会按照自然顺序或指定的比较器进行排序。 - List:基于数组或链表实现,
ArrayList
基于动态数组,LinkedList
基于双向链表。ArrayList
在随机访问元素时性能较好,因为可以通过索引直接访问数组中的元素;LinkedList
在插入和删除元素时性能较好,因为只需要修改链表的指针。 - Set:基于
Map
实现,HashSet
基于HashMap
,TreeSet
基于TreeMap
。HashSet
利用HashMap
的键的唯一性来保证元素的唯一性;TreeSet
利用TreeMap
的键的排序功能来保证元素的有序性。
- 要点
- 存储方式:
- Map:存储键值对,通过键来查找值。
- List:按顺序存储元素,可以通过索引访问元素。
- Set:存储不重复的元素,没有直接的索引访问方式。
- 访问方式:
- Map:通过键访问值,时间复杂度为 O (1)(
HashMap
)或 O (log n)(TreeMap
)。 - List:通过索引访问元素,时间复杂度为 O (1)(
ArrayList
)或 O (n)(LinkedList
)。 - Set:通常通过迭代器遍历元素,时间复杂度为 O (n)。
- Map:通过键访问值,时间复杂度为 O (1)(
- 元素特性:
- Map:键必须唯一,值可以重复。
- List:允许元素重复,元素有顺序。
- Set:不允许元素重复,元素没有特定的顺序(
TreeSet
除外)。
- 应用
在需要存储具有映射关系的数据时,使用 Map
;在需要按顺序存储元素,并且可能需要频繁访问元素时,使用 List
;在需要存储不重复的元素时,使用 Set
。在多线程环境下,可以使用 ConcurrentHashMap
、CopyOnWriteArrayList
、ConcurrentSkipListSet
等线程安全的集合类。例如,在一个电商系统中,可以使用 Map
存储商品的 ID 和商品信息的映射关系;使用 List
存储用户的订单列表;使用 Set
存储用户的收藏商品列表。
9. 什么是 Session 和 COOKIE,有什么区别
- Session:是服务器端的会话机制,用于跟踪用户的会话状态。服务器为每个用户创建一个唯一的会话对象,存储用户的相关信息。会话对象通常存储在服务器的内存中,也可以持久化到磁盘。
- COOKIE:是客户端的会话机制,服务器将一些信息以文本形式发送给客户端浏览器,浏览器将这些信息存储在本地。下次浏览器向服务器发送请求时,会将这些信息一起发送给服务器。
- 原理
- Session:服务器在创建会话对象时,会为每个会话分配一个唯一的会话 ID,并将该 ID 以 COOKIE 的形式发送给客户端。客户端下次请求时,会携带该会话 ID,服务器根据会话 ID 找到对应的会话对象。如果客户端浏览器禁用了 COOKIE,也可以通过 URL 重写的方式将会话 ID 传递给服务器。
- COOKIE:服务器通过响应头
Set - Cookie
将 COOKIE 信息发送给客户端,客户端浏览器将 COOKIE 存储在本地,并在下次请求时通过请求头Cookie
将 COOKIE 信息发送给服务器。COOKIE 可以设置不同的属性,如名称、值、过期时间、路径、域名等。
- 要点
- 存储位置:
- Session:信息存储在服务器端,客户端只保存会话 ID。
- COOKIE:信息存储在客户端,包括用户的一些信息(如用户名、偏好设置等)。
- 安全性:
- Session:相对安全,因为信息存储在服务器端,客户端无法直接访问和修改。
- COOKIE:安全性较低,因为信息存储在客户端,可能会被窃取或篡改。例如,攻击者可以通过中间人攻击获取用户的 COOKIE 信息,从而冒充用户登录系统。
- 数据大小限制:
- Session:没有数据大小限制,因为服务器可以根据需要分配内存来存储会话信息。
- COOKIE:有数据大小限制,一般不超过 4KB。如果需要存储大量数据,建议使用 Session。
- 有效期:
- Session:有一定的有效期,过期后会自动销毁。可以通过设置会话的超时时间来控制有效期。
- COOKIE:可以设置不同的有效期,包括会话级 COOKIE(浏览器关闭即失效)和持久化 COOKIE(可以设置过期时间)。
- 应用
在 Web 应用中,通常会结合使用 Session
和 COOKIE
。例如,使用 COOKIE
存储一些不敏感的信息(如用户的偏好设置),使用 Session
存储用户的登录状态等敏感信息。在分布式系统中,需要使用分布式会话管理技术来管理 Session
,如使用 Redis 等缓存服务器来存储会话信息,以保证不同服务器之间的会话一致性。
10. 什么是 IO、NIO、BIO、AIO、select、epoll,有什么区别
- IO(Input/Output):是 Java 中用于处理输入输出的基本机制,分为字节流和字符流。传统的 IO 是阻塞式的,即当进行读写操作时,线程会一直阻塞直到操作完成。
- BIO(Blocking IO):是传统的阻塞式 IO 模型,在进行读写操作时,线程会被阻塞,直到数据读写完成。在高并发场景下,需要为每个连接创建一个线程,会导致线程资源的浪费。
- NIO(Non - Blocking IO):是 Java 1.4 引入的非阻塞式 IO 模型,它基于通道(
Channel
)和缓冲区(Buffer
)进行操作。线程可以在进行读写操作时不被阻塞,而是可以继续处理其他任务。通过选择器(Selector
)可以实现一个线程管理多个通道。 - AIO(Asynchronous IO):是 Java 7 引入的异步 IO 模型,它是基于事件和回调机制的。当进行读写操作时,线程不会阻塞,而是在操作完成后通过回调函数通知线程。
- select:是一种传统的多路复用机制,用于监控多个文件描述符的状态变化。它有文件描述符数量的限制,一般为 1024。
- epoll:是 Linux 内核提供的一种高效的多路复用机制,它克服了
select
的一些缺点,没有文件描述符数量的限制,并且性能更高。
- 区别要点
- 阻塞与非阻塞:
- BIO:是阻塞式的,线程在进行读写操作时会被阻塞,直到操作完成。
- NIO:是非阻塞式的,线程可以在进行读写操作时继续处理其他任务。
- AIO:是异步非阻塞式的,线程在进行读写操作时不会阻塞,操作完成后通过回调函数通知线程。
- 多路复用机制:
- NIO:基于
select
或epoll
等多路复用机制,一个线程可以管理多个通道。通过选择器可以监控多个通道的状态变化,当某个通道有数据可读或可写时,线程才会进行相应的操作。 - AIO:基于事件和回调机制,不需要使用多路复用器。当读写操作完成时,操作系统会自动触发回调函数。
- NIO:基于
- 应用场景:
- BIO:适用于连接数较少且固定的场景,如一些传统的单机应用。
- NIO:适用于连接数较多但连接时间较短的场景,如 Web 服务器、即时通讯系统等。
- AIO:适用于连接数较多且连接时间较长的场景,如文件服务器、数据库服务器等。
- 应用
在开发高性能的网络应用时,如 Web 服务器、即时通讯系统等,通常会使用 NIO
或 AIO
模型。在 Linux 系统中,epoll
是实现 NIO
的首选多路复用机制。在使用 NIO
时,需要注意选择器的使用和缓冲区的管理,避免出现死锁和内存泄漏等问题。在使用 AIO
时,需要处理好回调函数的异常情况,确保程序的稳定性。
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90493963
相关文章:
Java面试黄金宝典2
1. 什么是 Concurrent 包 java.util.concurrent(简称 Concurrent 包)是 Java 5 引入的一个用于并发编程的工具包。它提供了一系列用于处理多线程编程的类和接口,帮助开发者更方便、安全地进行并发编程。 原理 该包基于 Java 的多线程机制和锁…...
【在数轴上找最优位置,使移动距离最短】
L1-4 破碎的心,无法挽回的距离 题目描述: YFffffff 最近在感情上遭受了失败,他的心也破碎成了n块碎片,散落在了数轴上的 n 个位置。 你是一个情感修复师,作为 YFffffff 的好友,你试图将这些破碎的心重新聚集到一个位…...
3D标定中的平面约束-平面方程的几何意义
平面方程的一般形式为 AxByCzD0,其中系数 A、B、C、D共同决定了平面的几何特性。 系数对平面姿态的影响 1. 法向量方向2. 平面位置3. 比例关系4. 姿态变换5.平面空间变换 1. 法向量方向 法向量方向由 A、B、C 决定 核心作用:系数 A、B、C 构成的向量 (…...
singleInstance 和 singleTask的 重要 区别
singleInstance 和 singleTask 是 Android 中 Activity 的两种启动模式,它们主要用于控制 Activity 在任务栈中的行为。以下是两者的区别: 1. singleTask 定义: 每个 singleTask 模式的 Activity 在一个任务栈中只会存在一个实例。行为: 如果该 Activi…...
【如何在OpenWebUI中使用FLUX绘画:基于硅基流动免费API的完整指南】
如何在OpenWebUI中使用FLUX绘画:基于硅基流动免费API的完整指南 注册并获取硅基流动秘钥OpenWebUI中使用函数配置自定义模型-提示词配置效果验证 ) FLUX绘画是一种强大的AI绘图工具,本文将详细介绍如何在OpenWebUI中集成并使用FLUX绘画功能,…...
【Linux】浅谈环境变量和进程地址空间
一、环境变量 基本概念 环境变量(Environment Variables)是操作系统提供的一种机制,用于存储和传递配置信息、系统参数、用户偏好设置等。 环境变量的作用 配置程序行为: 程序可以通过环境变量获取配置信息,例如日…...
vue数字公式篇(一)
一、使用插件来创造数字公式 因为只是展示和编辑 我看这个公式挺多,也对公式不太了解所以就这样,开始我的代码展示了 1、安装mathlive cnpm install mathlive2、页面 <template><div><label>输入 LaTeX 公式:</label><div …...
基于PMU的14节点、30节点电力系统状态估计MATLAB程序
“电气仔推送”获得资料(专享优惠) 程序简介: 程序采用三种方法对14节点和30节点电力系统状态进行评估: ①PMU同步向量测量单元结合加权最小二乘法(WLS)分析电力系统的电压幅值和相角状态; …...
5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)
最近很多朋友都在问:怎么本地部署 DeepSeek 搭建个人知识库。 老实说,如果你不是为了研究技术,或者确实需要保护涉密数据,我真不建议去折腾本地部署。 为什么呢? 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力…...
QT QML实现音频波形图进度条,可点击定位或拖动进度
前言 本项目实现了使用QT QML创建一个音频波形图进度条的功能。用户可以在界面上看到音频波形图,并且可以点击进度条上的位置进行定位,也可以拖动进度条来调整播放进度。可以让用户更方便地控制音频的播放进度,并且通过音频波形图可以直观地…...
浅谈StarRocks SQL性能检查与调优
StarRocks性能受数据建模、查询设计及资源配置核心影响。分桶键选择直接决定数据分布与Shuffle效率,物化视图可预计算复杂逻辑。执行计划需关注分区裁剪、谓词下推及Join策略,避免全表扫描或数据倾斜。资源层面,需平衡并行度、内存限制与网络…...
味觉传送器E-Taste:开启虚拟世界的味觉之门
味觉传送器E-Taste:开启虚拟世界的味觉之门 一、发明背景与动机 随着虚拟现实(VR)和增强现实(AR)技术的飞速发展,人们在虚拟世界中的沉浸感不断提升,视觉和听觉体验已经取得了显著的突破。然而…...
ISE 14.7 IP核 Block Memory Generator 更换coe
ISE 14.7 IP核 Block Memory Generator 更换coe 打开XCO 后缀,修改下面的coe_file 目录,并且重新regenerate ip 核即可...
【Auto-Scroll-List 组件设计与实现分析】
Auto-Scroll-List 组件设计与实现分析 gitee代码仓库 https://gitee.com/chennaiyuan/dayup-record/tree/master/%E4%B8%80%E4%BA%9B%E7%BB%84%E4%BB%B6/auto-scroll-list 1. 组件概述 我们封装的 AutoScrollList 是一个自动滚动列表组件,主要用于展示需要自动循…...
用hexo初始化博客执行hexo init时碰到的问题
用hexo初始化博客执行hexo init时碰到的问题 $ hexo init myblog INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git fatal: unable to access https://github.com/hexojs/hexo-starter.git/: SSL certificate problem: unable to get local issuer cer…...
【C++真题】P1739 表达式括号匹配
P1739 表达式括号匹配 题目描述 假设一个表达式有英文字母(小写)、运算符(、-、*、/)和左右小(圆)括号构成,以 作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配&#x…...
Java1.8与testNg兼容问题:bad class file和SocketTimeoutException: Read timed out
背景: 公司 java JDK默认用的是1.8版本,已经在跑的一个项目使用的testng用的是6.14.3,我拿到后通过Test 运行失败,因为这个是一直在用的项目,就没想到是版本兼容问题,折腾了好一阵(原开发者是通…...
高项第十二章——项目质量管理
项目质量管理包括把组织的质量政策应用于规划、管理、控制项目和产品质量要求,以满足干系人目标的各个过程。 项目质量管理针对的是项目过程中所涉及的活动 可交付成果质量管理针对的是项目生产的具体可交付成果,与可交付成果的性质和特性紧密相关 12…...
C# WPF编程-Menu
C# WPF编程-Menu 布局:代码:效果 在WPF(Windows Presentation Foundation)中,Menu控件用于创建下拉菜单或上下文菜单,它提供了丰富的定制选项来满足不同的应用需求。下面将介绍如何在WPF应用程序中使用Menu…...
python日期
导入包 from datetime import datetime现在时间 now datetime.now() print("当前时间:", now)当前时间: 2025-03-18 23:51:08.418953 格式化 formatted_now datetime.now().strftime("%Y-%m-%d %H:%M:%S") print("格式化后的时间:", forma…...
flutter 专题 一百零三
前不久,谷歌官方正式发布了Flutter的首个发布预览版(Release Preview 1),这标志着谷歌进入了Flutter正式版(1.0)发布前的最后阶段,同时作为Google的重量级跨平台开发方案,此次更新也…...
【conda activate无效】 conda: error: argument COMMAND: invalid choice: ‘activate‘
conda activate失效了 在使用conda activate时出现报错: usage: conda [-h] [-v] [--no-plugins] [-V] COMMAND ... conda: error: argument COMMAND: invalid choice: activate (choose from clean, compare, config, create, info, init, install, list, notice…...
Chainlit 自定义元素开发指南:使用 JSX 和受限导入实现交互式界面
自定义元素 Custom Element 类允许你渲染一个自定义的 .jsx 代码片段。.jsx 文件应当放置在 public/elements/ELEMEN_NAME.jsx 目录下。 属性 name 字符串 自定义元素的名称。它应该与你的JSX文件名相匹配(不包括 .jsx扩展名)。 props 字典 传递给 JSX 的属性。 display El…...
CEF 控制台添加一函数,枚举 注册的供前端使用的CPP交互函数有哪些
一、前序知识 1、设置单进程模式,方便调试 void ClientApp::OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr<CefCommandLine> command_line) {if (process_type.empty()){//cef 在debug模式下有问题#ifdef _DEBUGcommand_line->Appe…...
C++之list类及模拟实现
目录 list的介绍 list的模拟实现 定义节点 有关遍历的重载运算符 list的操作实现 (1)构造函数 (2)拷贝构造函数 (3)赋值运算符重载函数 (4)析构函数和clear成员函数 (5)尾…...
C++八大常见的设计模式的实现与实践指南
目录 创建型模式 单例模式工厂方法模式抽象工厂模式 结构型模式 适配器模式装饰者模式代理模式 行为型模式 观察者模式策略模式命令模式 高级主题 现代C特性影响模式性能对比典型应用案例 设计模式分类 一、创建型模式 1. 单例模式(Singleton) 现代…...
02 windows qt配置ffmpeg开发环境搭建
版本说明 首先我使用ffmpeg版本是4.2.1QT使用版本5.14.2我选择是c编译...
什么是状态管理?有何种方式可以实现?它们之间有什么区别?
目录 一、状态管理的核心概念 二、常见状态管理方案及对比 1. 基础方案:setState 2. 官方推荐:Provider 3. 事件驱动:Bloc (Business Logic Component) 4. 响应式增强:Riverpod 5. 轻量级全能库:GetX 三、方案对比与选型指南 四、实战建议 在 Flutter 中,状态管…...
tf1.x和tf2.x在使用上的区别和联系是什么
tf1.x和tf2.x在使用上的区别和联系是什么 TensorFlow 1.x 和 2.x 在使用上有显著差异,主要体现在编程范式、API 设计和易用性上,但二者仍共享相同的核心目标(深度学习框架)和底层计算引擎。以下是主要区别和联系: 主要…...
Elasticsearch使用记录
一、配环境 1.docker版本部署es 8.x系列可以关掉ssl(本地测试时),去docker的/usr/share/elasticsearch/config/elasticsearch.yml里面的“xpack.security.enabled:”设置成true就可以 2.window docker部署推荐教程:基于Docker安…...
【python web】一文掌握 Flask 的基础用法
文章目录 一、 Flask 介绍1.1 安装 Flask二、Flask的基本使用2.1 创建第一个 Flask 应用2.2 路由与视图函数2.3 请求与响应2.4 响应对象2.5 模板渲染2.6 模板继承2.7 静态文件管理2.8 Blueprint 蓝图2.9 错误处理三、Flask扩展与插件四、部署 Flask 应用五、总结Flask 是一个轻…...
第十六届蓝桥杯单片机组4T模拟赛二
难点: PCF8591同时测量两条通道数据 避免重复触发 采集触发时的时间数据存放 未采集的数据显示 清空数据 本题建议了解怎么去触发采集,怎么显示最近三次触发采集的时间即可。由于4T模拟赛的尿性有很多评测点是题目中没有要求的,另外测评的时候…...
《解锁华为黑科技:MindSpore+鸿蒙深度集成奥秘》
在数字化浪潮汹涌澎湃的当下,人工智能与操作系统的融合已成为推动科技发展的核心驱动力。华为作为科技领域的先锋,其AI开发框架MindSpore与鸿蒙系统的深度集成备受瞩目,开启了智能生态的新篇章。 华为MindSpore:AI框架的创新先锋…...
kotlin中的list set map整理
在 Kotlin 中,List、Set 和 Map 是三种核心集合类型,它们分别适用于不同的场景,具有独特的特性和操作方式。以下是它们的详细对比与使用指南: 1. List(列表) 核心特性 • 有序:元素按插入顺序…...
条款43:学习处理模板化基类内的名称
前提认知:模板类继承模板类,是需要建立在假设的前提下的,如果没有这个”假设“,编译将会失败 1.书上举例 2.完整代码举例 #include <iostream>class MsgInfo { };class BaseCompany { public:BaseCompany(){}~BaseCompan…...
五种方案实现双链路可靠数据传输
本文介绍五种双链路数据传输方案,目标是利用设备的多个传输通道,(如双有线网口,网口+wifi, 网口+5G等场景 , 网口+ 自组网, 自组网 + 5G等),将数据复制后分流、分路同时传输,以期提高数据传输可靠性,满足高可靠性传输的应用场景需求。部分方案给出了实际验证结果 。 …...
提升AI性能的秘密武器:量化、蒸馏与剪枝全面解析
通过高效的模型压缩技术推进 NLP 在快速发展的自然语言处理 (NLP) 领域,模型的大小和复杂性显著增加,从而显著提高了性能。然而,这些庞大模型的部署和维护也带来了挑战,特别是在计算成本、功耗和资源受限用户的可访问性方面。本博客深入探讨了量化、剪枝和蒸馏等尖端模型压…...
React Native 如何使用 Expo 快速开发?
React Native是当下热门的跨平台移动开发框架,而Expo则是它的重要开发工具之一。Expo提供了一套完整的开发环境,使开发者无需安装Android Studio或Xcode也能快速运行React Native项目。它包含了众多内置API,如相机、地理位置、推送通知等&…...
C++Primer 拷贝控制示例
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
Qt 读取数据库
在 Qt 中读取数据库文件通常涉及以下步骤。这里以 SQLite 为例(Qt 内置支持),其他数据库(如 MySQL、PostgreSQL)需要对应驱动: 1. 添加 SQL 模块依赖 在项目文件 .pro 中添加: QT sql2. 基本…...
DeepSeek在学术研究方向初期工作提示词分享
目录 论文选题 研读文献 拟定提纲 大家好这里是AIWritePaper官方账号!更多内容👉AIWritePaper~在如今这个学术圈的“快车道”上,时间就像是一场永不停歇的赛跑,而论文质量则是那颗我们拼命追逐的“金苹果”。最近一款名为DeepS…...
CentOS下安装ElasticSearch(日志分析)
准备目录 搞一个自己喜欢的目录 mkdir /usr/local/app 切换到该目录 cd /usr/local/app 下载 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.2-linux-x86_64.tar.gz 选择其他版本 点击进入官网...
科技云报到:AI Agent打了个响指,商业齿轮加速转动
科技云报到原创。 3月16日,百度旗下文心大模型4.5和文心大模型X1正式发布。目前,两款模型已在文心一言官网上线,免费向用户开放。 同时,文心大模型4.5已上线百度智能云千帆大模型平台,企业用户和开发者登录即可调用AP…...
布谷直播系统源码开发实战:从架构设计到性能优化
作为山东布谷科技的一名技术研发人员,我参与了多个直播系统平台从0到1的开发和搭建,也见证了直播行业从萌芽到爆发的全过程。今天,我想从研发角度,分享一些直播系统软件开发的经验和心得,希望能对大家有所帮助。 一、 …...
pytorch小记(十):pytorch中torch.tril 和 torch.triu 详解
pytorch小记(十):pytorch中torch.tril 和 torch.triu 详解 PyTorch torch.tril 和 torch.triu 详解1. torch.tril(计算下三角矩阵)📌 作用🔍 语法🔹 参数📌 示例…...
C语言每日一练——day_11
引言 针对初学者,每日练习几个题,快速上手C语言。第十一天。(连续更新中) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中…...
HCIA-PPP实验
一、LCP链路控制协议 1、链路建立阶段:通过交互LCP报文协商参数,包含了MRU、认证类型、魔术字等。 2、链路维护阶段: 3、链路终止 二、NCP网络控制协议:交互PPP IPCP报文,检测地址、学习路由、下发地址 1、通过IPCP协议的请求消…...
C++学习之云盘项目nginx
1.复习 2.知识点概述 1. 一些基本概念 1.1 Nginx 初步认识 1.2 正向 / 反向代理 1.3 域名和 IP 2. Nginx 安装和配置 2.1 安装 2.2 配置 3. Nginx 的使用 3.1 部署静态网页 3.2 反向代理和负载均衡 课外知识导读 1. URL 和 URI 2. DNS 解析过程 1. 一些基…...
7-字符串
1-ASCII 0-9 对应 48-57 A-Z 对应 65-90 a-z 对应 97-122 2-字符数组 字符变量存储单个字符 字符数组存储多个字符 字符串就是字符数组加上结束符 ’ \0 ’ #include <iostream> using namespace std; int main(){//是字符数组,不是字符串char a1[]{C,,};…...
vue学习八
十七 组件通信方式 1 props 父传子 //父组件 <script setup>//book来源省略import Subview1 from ./Subview1.vue;function updatebook(updatetimes){book.value.updatetimes updatetimes} </script> <template><Subview1 :book"book" :upd…...