一、Java虚拟机与平台特性
1. JVM架构详解
类加载器子系统:
- 启动类加载器(Bootstrap):加载
rt.jar等核心库
- 扩展类加载器(Extension):加载
jre/lib/ext目录
- 应用类加载器(Application):加载
CLASSPATH路径
- 自定义类加载器:继承
ClassLoader实现热部署
运行时数据区:
垃圾回收机制:
- 分代收集:新生代(Eden+S0+S1)和老年代
- GC算法:
- 标记-清除:产生内存碎片
- 复制算法:适用于新生代(90%对象存活率低)
- 标记-整理:适用于老年代
- 常见GC器:
- Serial:单线程,适合客户端应用
- Parallel:多线程吞吐量优先
- CMS:低延迟,但会产生碎片
- G1:分区收集,预测停顿时间
2. 跨平台原理
- 字节码文件(
.class):
- 由Java编译器生成,与操作系统无关
- 包含:常量池、字段表、方法表、属性表
- JVM执行过程:
1 2 3 4 5
| public class Test { public static void main(String[] args) { System.out.println("Hello"); } }
|
- 编译后字节码(
javap -c Test.class): 1 2 3 4 5 6
| public static void main(java.lang.String[]); Code: 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String Hello 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return
|
二、基础语法与数据类型
1. 基本数据类型解析
| 基本类型 |
包装类 |
大小 |
默认值 |
取值范围 |
特殊说明 |
byte |
Byte |
1字节 |
0 |
-128~127 |
适合存储小整数 |
short |
Short |
2字节 |
0 |
-32768~32767 |
|
int |
Integer |
4字节 |
0 |
-2^31~2^31-1 |
最常用整型 |
long |
Long |
8字节 |
0L |
-2^63~2^63-1 |
后缀L |
float |
Float |
4字节 |
0.0f |
±3.40282347E+38F |
后缀f |
double |
Double |
8字节 |
0.0d |
±1.79769313486231570E+308 |
默认浮点类型 |
char |
Character |
2字节 |
‘\u0000’ |
0~65535 |
Unicode字符 |
boolean |
Boolean |
1位 |
false |
true/false |
无具体大小 |
关键说明
- 包装类均为引用类型,首字母大写(两个特殊情况:
int 对应 Integer、char 对应 Character,其余基本类型直接首字母大写即可)
- 包装类主要用于需要使用对象的场景(如集合框架、反射等),可实现基本类型与包装类的自动装箱/拆箱
自动类型转换规则:
1 2 3 4
| int a = 10; double b = a; long c = 100L; int d = (int)c;
|
装箱拆箱细节:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| 将基本类型(如 int)自动转换为包装类(如 Integer)。 编译后等价于:Integer x = Integer.valueOf(100);
将包装类(如 Integer)自动转换为基本类型(如 int)。 编译后等价于:int y = x.intValue();
Integer x = 100; int y = x;
Integer a = 100; Integer b = 100; System.out.println(a == b);
Integer c = 200; Integer d = 200; System.out.println(c == d);
1.让基本类型“对象化” Java 的泛型、集合框架、反射、注解等机制只能操作对象(引用类型),不能操作基本类型。包装类(如 Integer)将基本类型“封装”为对象,解决了这一矛盾。
2.支持 null 值 基本类型(如 int)必须有默认值(int 默认是 0),无法表示“无值”状态。 包装类可以为 null,适用于需要“可选值”的场景 Integer age = null; int age = 0;
3.提供丰富的实用方法 int num = Integer.parseInt("123"); String binary = Integer.toBinaryString(10); int max = Integer.max(10, 20);
|
2. 字符串处理深度
三、正则表达式深度解析
正则表达式(Regular Expression)是处理字符串的强大工具,用于匹配、查找、替换符合特定规则的文本。Java中通过java.util.regex包提供正则支持,核心类为Pattern(编译正则表达式)和Matcher(执行匹配操作)。
1. 正则表达式基本语法
(1)字符匹配
| 语法 |
描述 |
示例 |
| 普通字符 |
匹配自身 |
abc 匹配 “abc” |
. |
匹配任意单个字符(除换行符) |
a.c 匹配 “abc”、”a1c” |
[abc] |
匹配括号内任意一个字符 |
[abc] 匹配 “a”、”b”、”c” |
[^abc] |
匹配不在括号内的任意字符 |
[^abc] 匹配 “d”、”1” |
[a-z] |
匹配指定范围的字符 |
[0-9a-zA-Z] 匹配数字或字母 |
\d |
等价于 [0-9](数字) |
\d{3} 匹配 “123” |
\D |
等价于 [^0-9](非数字) |
\D 匹配 “a”、”!” |
\w |
等价于 [a-zA-Z0-9_](单词字符) |
\w+ 匹配 “user123” |
\W |
等价于 [^a-zA-Z0-9_](非单词字符) |
\W 匹配 “@”、”#” |
\s |
匹配空白字符(空格、制表符等) |
a\sb 匹配 “a b”、”a\tb” |
\S |
匹配非空白字符 |
a\Sb 匹配 “a1b”、”a@b” |
(2)量词(控制匹配次数)
| 语法 |
描述 |
示例 |
* |
匹配前一个元素0次或多次(贪婪模式) |
a* 匹配 “”、”a”、”aa” |
+ |
匹配前一个元素1次或多次(贪婪模式) |
a+ 匹配 “a”、”aa” |
? |
匹配前一个元素0次或1次(贪婪模式) |
a? 匹配 “”、”a” |
{n} |
匹配前一个元素恰好n次 |
a{3} 匹配 “aaa” |
{n,} |
匹配前一个元素至少n次 |
a{2,} 匹配 “aa”、”aaa” |
{n,m} |
匹配前一个元素n到m次 |
a{1,3} 匹配 “a”、”aa”、”aaa” |
*?/+?/?? |
非贪婪模式(尽可能少匹配) |
"a.*?b" 匹配 “aab” 中的 “aab”(而非贪婪的 “aab…b”) |
(3)边界匹配
| 语法 |
描述 |
示例 |
^ |
匹配字符串开始位置 |
^abc 匹配 “abc123”(不匹配 “xabc”) |
$ |
匹配字符串结束位置 |
abc$ 匹配 “123abc”(不匹配 “abcx”) |
\b |
匹配单词边界(单词与非单词字符之间) |
\bcat\b 匹配 “cat”(不匹配 “category” 中的 “cat”) |
\B |
匹配非单词边界 |
\Bcat\B 匹配 “category” 中的 “cat” |
(4)分组与捕获
| 语法 |
描述 |
示例 |
(pattern) |
分组,将pattern视为一个整体,可捕获匹配结果 |
(ab)+ 匹配 “abab” |
\n |
引用第n个分组的匹配结果(n为1-9) |
(a)\1 匹配 “aa” |
(?:pattern) |
非捕获分组(仅分组不捕获结果) |
(?:ab)+ 匹配 “abab” 但不保存分组 |
(?<name>pattern) |
命名分组(通过名称引用) |
(?<id>\d+) 匹配数字并命名为”id” |
(5)逻辑运算符
| 语法 |
描述 |
示例 |
| ` |
` |
逻辑或,匹配左边或右边的表达式 |
() |
结合逻辑或 |
`(ab |
2. Java正则核心类(Pattern与Matcher)
(1)Pattern类(编译正则表达式)
- 作用:预编译正则表达式为Pattern对象(线程安全,可复用)。
- 常用方法:
Pattern.compile(String regex):编译正则表达式。
Pattern.matches(String regex, CharSequence input):快速匹配(等价于编译后直接调用matches())。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import java.util.regex.Pattern; import java.util.regex.Matcher;
public class MatcherDemo { public static void main(String[] args) { Pattern pattern = Pattern.compile("\\d{3}"); String input = "abc123def456ghi78"; Matcher matcher = pattern.matcher(input); } }
|
(2)Matcher类(执行匹配操作)
- 作用:通过Pattern对象创建,用于对输入字符串执行匹配操作。
- 常用方法:
matches():整个字符串是否完全匹配正则。
find():查找字符串中是否有匹配的子序列(可多次调用,每次找下一个)。
group():获取匹配的子序列(结合分组使用)。
start()/end():获取匹配子序列的起始/结束索引。
replaceAll(String replacement):替换所有匹配的子序列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| import java.util.regex.Pattern; import java.util.regex.Matcher;
public class MatcherMethodWithResultDemo { public static void main(String[] args) { Pattern pattern = Pattern.compile("\\d+"); String inputStr = "abc123def456ghi7890"; Matcher matcher = pattern.matcher(inputStr);
System.out.println("===== matches() 全量匹配 ====="); boolean isFullMatch = matcher.matches(); System.out.println("整个字符串是否完全匹配数字:" + isFullMatch);
matcher.reset();
System.out.println("\n===== find() + group() + start()/end() 查找与提取 ====="); while (matcher.find()) { String matchContent = matcher.group(); int startIndex = matcher.start(); int endIndex = matcher.end();
System.out.printf("匹配到数字:%s,起始索引:%d,结束索引:%d,对应区间:[%d, %d)%n", matchContent, startIndex, endIndex, startIndex, endIndex); }
System.out.println("\n===== group() 分组提取 ====="); Pattern groupPattern = Pattern.compile("(\\d{2})(\\d+)"); Matcher groupMatcher = groupPattern.matcher(inputStr); while (groupMatcher.find()) { String fullMatch = groupMatcher.group(0);
String group1 = groupMatcher.group(1);
String group2 = groupMatcher.group(2);
System.out.printf("完整匹配:%s,分组1(前2位):%s,分组2(剩余):%s%n", fullMatch, group1, group2); }
System.out.println("\n===== replaceAll() + replaceFirst() 替换 ====="); matcher.reset(); String replaceAllResult = matcher.replaceAll("【数字】"); System.out.println("替换所有数字后的结果:" + replaceAllResult);
matcher.reset(); String replaceFirstResult = matcher.replaceFirst("【首个数字】"); System.out.println("只替换第一个数字后的结果:" + replaceFirstResult); } }
|
3. 常用场景示例
(1)数据验证
1 2 3 4 5 6 7
| String emailRegex = "^[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z0-9]+)+$"; boolean isEmail = "user@example.com".matches(emailRegex);
String phoneRegex = "^1[3-9]\\d{9}$"; boolean isPhone = "13812345678".matches(phoneRegex);
|
(2)文本提取
1 2 3 4 5 6 7 8 9 10 11
| String html = "<a href='https://a.com'>链接1</a><a href='https://b.com'>链接2</a>"; Pattern linkPattern = Pattern.compile("href=['\"](.*?)['\"]"); Matcher matcher = linkPattern.matcher(html);
while (matcher.find()) { System.out.println("链接:" + matcher.group(1)); }
|
(3)文本替换
1 2 3 4
| String text = "密码:123456,验证码:789"; String replaced = text.replaceAll("\\d", "*"); System.out.println(replaced);
|
四、数组与集合框架
1. 数组底层实现
- 内存布局:
1 2 3
| int[] arr = new int[3];
|
- 多维数组:
1 2 3 4 5
| int[][] matrix = new int[2][3];
|
2. 集合框架深度解析
(1) List实现类
| 类型 |
底层结构 |
扩容机制 |
特点 |
适用场景 |
| ArrayList |
动态数组 |
1.5倍扩容 |
随机访问快 插入删除慢 |
频繁查询 较少修改 |
| LinkedList |
双向链表 |
无扩容 |
插入删除快 随机访问慢 |
频繁增删 较少查询 |
ArrayList扩容细节:
1 2 3 4 5 6 7 8 9 10
| private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }
|
ArrayList常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import java.util.ArrayList; import java.util.List;
public class ArrayListSimpleDemo { public static void main(String[] args) { List<String> arrayList = new ArrayList<>();
arrayList.add("Java"); arrayList.add("Python"); arrayList.add("C++"); arrayList.add("Go"); System.out.println("初始ArrayList:" + arrayList);
String element1 = arrayList.get(1); String element2 = arrayList.get(2); System.out.println("索引1的元素:" + element1 + ",索引2的元素:" + element2);
arrayList.set(3, "Rust"); System.out.println("修改后ArrayList:" + arrayList);
arrayList.remove(2); System.out.println("删除索引2元素后:" + arrayList);
System.out.println("普通for循环遍历(适配ArrayList随机访问特性):"); for (int i = 0; i < arrayList.size(); i++) { System.out.println("索引" + i + ":" + arrayList.get(i)); } } }
|
LinkedList常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import java.util.LinkedList;
public class LinkedListSimpleDemo { public static void main(String[] args) { LinkedList<Integer> linkedList = new LinkedList<>();
linkedList.add(10); linkedList.add(20); linkedList.addFirst(5); linkedList.addLast(25); System.out.println("初始LinkedList:" + linkedList);
linkedList.add(2, 15); System.out.println("索引2插入15后:" + linkedList);
linkedList.removeFirst(); linkedList.removeLast(); System.out.println("删除头尾元素后:" + linkedList);
Integer element = linkedList.get(1); System.out.println("索引1的元素:" + element);
System.out.println("增强for循环遍历(适配LinkedList增删特性):"); for (Integer num : linkedList) { System.out.println(num); } } }
|
(2) Set实现类
| 类型 |
底层结构 |
排序特性 |
线程安全 |
特点 |
| HashSet |
HashMap |
无序 |
❌ |
通过hashCode()快速查找 |
| LinkedHashSet |
LinkedHashMap |
插入顺序 |
❌ |
保持插入顺序 |
| TreeSet |
TreeMap |
自然排序 |
❌ |
通过红黑树实现 |
HashSet:无序、去重(底层 HashMap)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.util.HashSet; import java.util.Set;
public class HashSetDemo { public static void main(String[] args) { Set<String> hashSet = new HashSet<>();
hashSet.add("Java"); hashSet.add("Python"); hashSet.add("Java"); hashSet.add("C++"); hashSet.add("Go");
System.out.println("HashSet元素(无序+去重):" + hashSet);
boolean hasPython = hashSet.contains("Python"); hashSet.remove("C++"); System.out.println("是否包含Python:" + hasPython); System.out.println("删除C++后HashSet:" + hashSet); } }
|
LinkedHashSet:保持插入顺序、去重(底层 LinkedHashMap)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import java.util.LinkedHashSet; import java.util.Set;
public class LinkedHashSetDemo { public static void main(String[] args) { Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Java"); linkedHashSet.add("Python"); linkedHashSet.add("Java"); linkedHashSet.add("C++"); linkedHashSet.add("Go");
System.out.println("LinkedHashSet元素(插入顺序+去重):" + linkedHashSet);
System.out.println("遍历LinkedHashSet(保持插入顺序):"); for (String str : linkedHashSet) { System.out.println(str); } } }
|
TreeSet:自然排序、去重(底层 TreeMap,红黑树)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.util.TreeSet; import java.util.Set;
public class TreeSetDemo { public static void main(String[] args) { Set<Integer> numTreeSet = new TreeSet<>(); numTreeSet.add(30); numTreeSet.add(10); numTreeSet.add(20); numTreeSet.add(30); System.out.println("TreeSet整数(自然升序+去重):" + numTreeSet);
Set<String> strTreeSet = new TreeSet<>(); strTreeSet.add("Java"); strTreeSet.add("Python"); strTreeSet.add("C++"); strTreeSet.add("Go"); System.out.println("TreeSet字符串(字典序+去重):" + strTreeSet); } }
|
(3) Map实现类
| 类型 |
底层结构 |
扩容机制 |
线程安全 |
特点 |
| HashMap |
数组+链表+红黑树 |
2倍扩容 |
❌ |
最常用Map |
| Hashtable |
数组+链表 |
2倍扩容 |
✅ |
同步,已过时 |
| ConcurrentHashMap |
分段锁(JDK7) CAS+synchronized(JDK8) |
2倍扩容 |
✅ |
高并发场景 |
| TreeMap |
红黑树 |
无 |
❌ |
按键排序 |
HashMap:最常用、无序、非线程安全(底层数组 + 链表 + 红黑树)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.util.HashMap; import java.util.Map;
public class HashMapDemo { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("张三", 25); hashMap.put("李四", 30); hashMap.put("王五", 28); hashMap.put("张三", 26);
int zhangSanAge = hashMap.get("张三"); System.out.println("张三的年龄:" + zhangSanAge);
System.out.println("HashMap键值对(无序):" + hashMap);
hashMap.put("李四", 31); hashMap.remove("王五"); System.out.println("修改+删除后HashMap:" + hashMap);
System.out.println("遍历HashMap:"); for (Map.Entry<String, Integer> entry : hashMap.entrySet()) { System.out.println("键:" + entry.getKey() + ",值:" + entry.getValue()); } } }
|
Hashtable:线程安全、已过时(底层数组 + 链表)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import java.util.Hashtable; import java.util.Map;
public class HashtableDemo { public static void main(String[] args) { Map<String, Integer> hashtable = new Hashtable<>();
hashtable.put("张三", 25); hashtable.put("李四", 30); hashtable.put("王五", 28); hashtable.put("张三", 26);
System.out.println("Hashtable键值对(线程安全+无序):" + hashtable);
System.out.println("注意:Hashtable已过时,优先使用ConcurrentHashMap实现线程安全Map"); } }
|
ConcurrentHashMap:高并发、线程安全(JDK8:CAS+synchronized)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import java.util.Map; import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo { public static void main(String[] args) throws InterruptedException { Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
Runnable task = () -> { for (int i = 0; i < 1000; i++) { concurrentHashMap.put(Thread.currentThread().getName() + "-" + i, i); } };
Thread t1 = new Thread(task, "线程1"); Thread t2 = new Thread(task, "线程2"); t1.start(); t2.start(); t1.join(); t2.join();
System.out.println("ConcurrentHashMap元素个数(并发写入无丢失):" + concurrentHashMap.size());
concurrentHashMap.put("张三", 25); System.out.println("张三的年龄:" + concurrentHashMap.get("张三")); } } ```
- **TreeMap:按键自然排序、非线程安全(底层红黑树)** ```java import java.util.TreeMap; import java.util.Map;
public class TreeMapDemo { public static void main(String[] args) { Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("张三", 25); treeMap.put("李四", 30); treeMap.put("王五", 28); treeMap.put("赵六", 35);
System.out.println("TreeMap键值对(按键字典序排序):" + treeMap);
System.out.println("遍历TreeMap(按键排序):"); for (Map.Entry<String, Integer> entry : treeMap.entrySet()) { System.out.println("键:" + entry.getKey() + ",值:" + entry.getValue()); }
Map<Integer, String> numTreeMap = new TreeMap<>(); numTreeMap.put(3, "C++"); numTreeMap.put(1, "Java"); numTreeMap.put(2, "Python"); System.out.println("TreeMap(键为整数,升序排序):" + numTreeMap); } }
|
(5)总结
| 实现类 |
核心特性体现 |
适用场景 |
| HashSet |
无序、去重 |
无需有序存储,仅需去重 |
| LinkedHashSet |
插入顺序、去重 |
需要保留插入顺序且去重 |
| TreeSet |
自然排序、去重 |
需要有序存储且去重 |
| HashMap |
高效、无序、非线程安全 |
普通场景(单线程/无并发)的键值对存储 |
| Hashtable |
线程安全、性能差、已过时 |
兼容旧系统,不推荐新开发使用 |
| ConcurrentHashMap |
高并发、线程安全、性能优异 |
多线程并发写入/读取的场景 |
| TreeMap |
按键自然排序、非线程安全 |
需要按键盘序遍历的键值对存储 |
五、面向对象深度解析
1. 继承与多态
多态实现原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Animal { void sound() { System.out.println("Animal"); } } class Dog extends Animal { @Override void sound() { System.out.println("Woof"); } }
Animal a = new Dog(); a.sound();
|
- JVM通过虚方法表(vtable) 实现
- 每个类有虚方法表,指向实际方法地址
super关键字详解:
1 2 3 4 5 6 7 8 9
| class Parent { Parent(String name) { } }
class Child extends Parent { Child() { super("Child"); } }
|
Override与super关键字
2. 抽象类
抽象类定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public abstract class Animal { public abstract void sound(); public void eat() { System.out.println("Animal is eating"); } }
public class Dog extends Animal { @Override public void sound() { System.out.println("Woof"); } }
|
知识点:
1 2 3 4 5 6 7 8 9 10
| 1.抽象类不能直接实例化(不能用 new AbstractClass() 创建对象),只能作为父类被子类继承。 补充:可通过“子类实例化+向上转型”的方式使用抽象类(如 AbstractAnimal animal = new Dog())。 2.成员组成: 抽象方法:用 abstract 修饰,无方法体(以分号结尾),表示“待子类实现的方法”,抽象类中可以有 0 个或多个抽象方法;不能被 private、final、static 修饰(会限制子类重写)。 普通方法:有完整方法体,供子类直接继承复用,无需子类重写(子类可按需重写,重写时遵循方法重写通用规则,访问权限不能比父类更严格)。 成员变量:支持普通成员变量(可修改,属于对象实例)、静态变量(static,属于抽象类本身,可通过类名直接访问),有默认初始化值。 构造器:存在构造器(用于子类初始化时,调用父类构造器初始化抽象类的成员变量),但不能用于实例化抽象类本身;子类构造器会默认隐式调用抽象类无参构造器(super()),若抽象类只有有参构造器,子类必须显式调用(super(参数))且放在第一行。 3.继承规则: 类继承抽象类时,要么自身也声明为抽象类(可遗留抽象方法,未实现的方法向下传递),要么必须实现抽象类的所有抽象方法。 Java 是单继承机制,一个子类只能继承一个抽象类(该规则适用于所有Java类,一个类仅有一个直接父类)。
|
3. 接口
接口定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public interface Animal { void sound(); default void eat() { System.out.println("Animal is eating"); } }
public class Dog implements Animal { @Override public void sound() { System.out.println("Woof"); } }
Animal myPet = new Dog(); myPet.sound();
|
知识点:
1 2 3 4 5 6 7 8 9 10
| 1. 接口是一种引用类型,用于定义行为规范(抽象方法)。 2. 接口不能直接实例化(不能用 new Interface() 创建对象),只能作为类型被实现或被其他接口继承。 3. java8之前: 接口可以包含常量(默认 public static final)和抽象方法(默认 public abstract)。 4. java8及以后: 在3的基础上,接口可以包含默认方法(default 修饰,有方法体)和静态方法(static 修饰,有方法体)。 注意:默认方法和静态方法不能使用 public abstract 修饰符(二者有方法体,与抽象方法特性冲突);接口的抽象方法仍默认携带 public abstract 修饰符,可省略不写。 5. 类实现接口时,必须实现接口中的所有抽象方法,否则类必须声明为抽象类。 6. 接口可以继承其他接口,形成接口的层次结构。
|
4. 抽象类与接口的联系总结
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 1. 抽象类可以没有抽象方法(但通常会有普通方法);即使无抽象方法,抽象类依然无法直接实例化。 2. 抽象方法不能被 private/final/static 修饰(冲突特性);核心原因:这三个修饰符会限制子类重写抽象方法(private不可访问、final不可重写、static不属于实例无法重写)。 3. 抽象类的构造器不能私有化(否则无法被继承)。 4. 抽象类可作为方法参数 / 返回值(体现多态);实际传入/返回的是抽象类的子类实例(向上转型)。 5. 抽象类可以继承抽象类: 子抽象类可选择性实现父抽象类的抽象方法(实现部分、实现全部、一个都不实现都可以),未实现的抽象方法会向下传递,由最终的非抽象子类统一实现。 从中也可以反映:抽象类可以有非抽象方法。 6. 抽象类可以实现接口的部分方法: 抽象类可以实现接口的部分方法(即实现接口的抽象方法),甚至可以一个都不实现;未实现的方法可以在抽象类中保持抽象状态,继续向下传递。 7. 普通类必须实现接口的所有抽象方法,否则类必须声明为抽象类。 8. 普通类继承抽象类时,必须实现抽象类的所有抽象方法,否则类必须声明为抽象类;此处的“所有抽象方法”包括抽象类自身定义的、继承父抽象类遗留的、实现接口传递下来的所有未完成抽象方法。 9. 类(普通类,内部类,抽象类)只能单继承,但可以实现多个接口。 10. 接口与抽象类的抽象方法: 接口: 1. 抽象方法默认修饰符是 public abstract,可省略不写(三种写法等价:void method(); / public void method(); / public abstract void method();)。 2. 有且仅有 public abstract 这一种修饰符组合,不允许使用 private、protected 等其他任何修饰符,否则编译报错。 3. 子类重写该抽象方法时,必须使用 public 修饰符(权限不能更严格)。 抽象类: 1. abstract 修饰符必须手动指定(不写则不是抽象方法),无默认的 public abstract/protected abstract 组合。 2. 访问修饰符支持 2 种:public、protected(可手动指定);若不指定任何访问修饰符,默认是「包访问权限(default 权限,无关键字)」,非 protected。 3. 不支持的修饰符:private、final、static(与 abstract 互斥,编译报错)。 4. 子类重写该抽象方法时,访问权限不能比父类更严格(如父类 protected → 子类 protected/public;父类 public → 子类只能 public)。
|
六、异常处理解析
1. 异常体系结构
- Checked Exception vs Unchecked Exception:
| 类型 |
特点 |
举例 |
处理要求 |
| Checked Exception |
编译时检查 |
IOException, SQLException |
必须捕获或声明抛出 |
| Unchecked Exception |
运行时异常 |
NullPointerException, IllegalArgumentException |
可选处理 |
2. 异常处理最佳实践
七、内部类解析
1. 四种内部类详解
| 类型 |
定义位置 |
访问外部类成员 |
实例化方式 |
特点 |
| 成员内部类 |
类中方法外 |
✅ 可直接访问 |
Outer.Inner in = new Outer().new Inner(); |
需外部类实例 |
| 静态内部类 |
类中方法外+static |
❌ 只能访问静态成员 |
Outer.StaticInner si = new Outer.StaticInner(); |
独立于外部类 |
| 局部内部类 |
方法内 |
✅ 可访问final局部变量 |
new Inner();(仅在方法内) |
作用域仅限方法 |
| 匿名内部类 |
无名,直接实例化 |
✅ |
new Interface() { ... } |
适用于单次使用 |
成员内部类示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Outer { private int outerField = 10; public class Inner { public void display() { System.out.println(outerField); } } }
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.display();
|
匿名内部类典型应用:
1 2 3 4 5 6 7 8 9 10
| new Thread(new Runnable() { @Override public void run() { System.out.println("Running"); } }).start();
new Thread(() -> System.out.println("Running")).start();
|
八、文件I/O与NIO.2
1. 传统IO流体系
| 类型 |
抽象类 |
具体实现 |
用途 |
| 字节流 |
InputStream/OutputStream |
FileInputStream/FileOutputStream |
二进制数据 |
| 字符流 |
Reader/Writer |
FileReader/FileWriter |
文本数据 |
| 缓冲流 |
BufferedInputStream/BufferedOutputStream |
BufferedInputStream/BufferedWriter |
提高读写效率 |
| 转换流 |
InputStreamReader/OutputStreamWriter |
InputStreamReader/OutputStreamWriter |
字节→字符转换 |
- 文件读写示例:
1 2 3 4 5 6 7 8 9 10 11 12
| try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } }
try (BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt", true))) { bw.write("New line"); }
|
2. NIO.2核心特性
Path与Files工具类:
1 2 3 4 5 6 7 8 9 10
| Path path = Paths.get("file.txt");
List<String> lines = Files.readAllLines(path);
Files.write(path, "New content".getBytes(), StandardOpenOption.CREATE);
Files.copy(Paths.get("source.txt"), Paths.get("dest.txt"), StandardCopyOption.REPLACE_EXISTING);
|
异步文件操作:
1 2 3 4 5 6 7 8 9 10 11 12 13
| AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get("file.txt"), StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, 0, null, new CompletionHandler<Integer, Object>() { @Override public void completed(Integer result, Object attachment) { System.out.println("Read " + result + " bytes"); } @Override public void failed(Throwable exc, Object attachment) { exc.printStackTrace(); } });
|
九、泛型
类型擦除原理
1 2 3 4 5 6 7 8 9 10 11 12
| List<String> list = new ArrayList<>(); list.add("Hello");
List list = new ArrayList(); list.add("Hello");
List<String> list1 = new ArrayList<>(); List<Integer> list2 = new ArrayList<>(); System.out.println(list1.getClass() == list2.getClass());
|
- 泛型基础
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| List box = new ArrayList(); box.add("苹果"); box.add(123); box.add(new Car());
String fruit = (String) box.get(0); int num = (int) box.get(1); int num = (Integer) box.get(1); Car car = (Car) box.get(2);
List<String> fruitBox = new ArrayList<>(); fruitBox.add("苹果"); fruitBox.add(123); fruitBox.add(new Car()); String fruit = fruitBox.get(0);
List<Integer> numberBox = new ArrayList<>(); numberBox.add(123);
int num = numberBox.get(0);
|
绕过类型擦除获取泛型类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class TypeReference<T> { private final Type type; protected TypeReference() { Type superclass = getClass().getGenericSuperclass(); type = ((ParameterizedType) superclass).getActualTypeArguments()[0]; } public Type getType() { return type; } }
TypeReference<List<String>> ref = new TypeReference<>() {}; System.out.println(ref.getType());
|
十、Lambda表达式(java 8+)
Lambda 表达式是 Java 8 引入的函数式编程特性,用于简化匿名内部类的写法。它的核心本质是:
将“行为”作为参数传递,让代码更简洁、更易读。
Lambda 表达式通用语法
(参数列表):函数的输入参数(可省略类型,由编译器自动推断)
->:箭头操作符(固定写法)
{ 代码块 }:函数体(单行表达式可省略 {} 和 return)
语法简化规则
1️⃣ 完整版(带类型和代码块)
1 2 3 4
| (int a, int b) -> { return a + b; }
|
2️⃣ 省略参数类型(编译器自动推断)
1 2 3 4
| (a, b) -> { return a + b; }
|
3️⃣ 单参数省略括号
4️⃣ 单行表达式省略 return 和 {}
5️⃣ 无参数时用空括号
1 2
| () -> System.out.println("Hello")
|
经典场景示例
✅ 场景 1:函数式接口实现
1 2 3 4 5 6 7 8 9 10 11 12
| @FunctionalInterface interface MathOperation { int operate(int a, int b); }
MathOperation add = (a, b) -> a + b; MathOperation multiply = (a, b) -> a * b;
System.out.println(add.operate(2, 3)); System.out.println(multiply.operate(2, 3));
|
✅ 场景 2:Stream API 过滤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream() .filter(x -> x % 2 == 0) .collect(Collectors.toList());
System.out.println(evenNumbers);
--------------
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * n) .reduce(0, Integer::sum);
int parallelSum = numbers.parallelStream() .mapToInt(n -> n * n) .sum();
|
✅ 场景 3:多参数 + 代码块
1 2 3 4 5 6 7 8 9
| Comparator<Integer> comparator = (a, b) -> { if (a > b) return 1; else if (a < b) return -1; else return 0; };
System.out.println(comparator.compare(3, 5));
|
✅ 场景 4:无参数(如 Runnable)
1 2 3 4 5 6 7 8 9 10
| new Thread(() -> System.out.println("Running")).start();
new Thread(new Runnable() { @Override public void run() { System.out.println("Running"); } }).start();
|
关键注意事项
| 规则 |
说明 |
示例 |
| 必须是函数式接口 |
Lambda 只能用于 只有一个抽象方法的接口(用 @FunctionalInterface 标注) |
Runnable, Comparator, Predicate 等 |
| 访问外部变量必须是 final 或 effectively final |
Lambda 内部不能修改外部变量(只能读取) |
int x = 10;
() -> System.out.println(x); // ✅
x = 20; // ❌ 编译错误 |
| 不能声明新变量 |
Lambda 表达式中不能声明新变量(如 int y = 5;) |
x -> { int y = x; return y; } // ❌ 编译错误 |
| 方法引用是 Lambda 的简写 |
用 :: 操作符引用已有方法 |
System.out::println 等价于 x -> System.out.println(x) |
Lambda语法总结
- 参数列表:可省略类型,单参数省略括号
- 箭头
->:固定符号
- 函数体:单行表达式省略
{} 和 return
十一、Optional类使用
Optional 类深度解析:彻底告别 NPE(空指针异常)
✅ 核心理念:
Optional 是 Java 8 引入的「容器类」,用于显式表达「值可能存在也可能不存在」,强制开发者处理空值场景,从根源上杜绝 NullPointerException。
为什么需要 Optional?
传统空值处理的痛点
1 2 3 4 5 6 7 8 9
| String name = null; if (user != null) { if (user.getAddress() != null) { if (user.getAddress().getCity() != null) { name = user.getAddress().getCity().getName(); } } }
|
- 问题:
- 代码冗长、可读性差
- 容易遗漏检查(导致运行时 NPE)
- null 语义不明确:无法区分「故意为 null」还是「忘记处理」
Optional 的解决方案
1 2 3 4 5 6
| String name = Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCity) .map(City::getName) .orElse("未知城市");
|
- 优势:
- 强制处理空值:编译器要求你显式处理
null 场景
- 链式调用:避免多层嵌套
if
- 语义明确:
Optional 本身表示「可能为空」,代码自解释
Optional 核心方法
1️⃣ 创建 Optional 实例
| 方法 |
说明 |
示例 |
适用场景 |
Optional.of(T value) |
包装非 null 值 |
Optional.of("Hello") |
值一定不为 null(否则抛 NullPointerException) |
Optional.ofNullable(T value) |
包装可能为 null 的值 |
Optional.ofNullable(user) |
值可能为 null(安全创建) |
Optional.empty() |
创建空 Optional |
Optional.empty() |
显式表示「无值」 |
2️⃣ 安全获取值
| 方法 |
说明 |
示例 |
风险 |
T get() |
直接获取值 |
optional.get() |
⚠️ 若为空则抛 NoSuchElementException(不推荐!) |
T orElse(T other) |
有值返回值,无值返回默认值 |
optional.orElse("default") |
安全(推荐) |
T orElseGet(Supplier supplier) |
有值返回值,无值执行 Supplier 生成默认值 |
optional.orElseGet(() -> generateDefault()) |
延迟计算(默认值创建成本高时用) |
T orElseThrow(Supplier exceptionSupplier) |
有值返回值,无值抛异常 |
optional.orElseThrow(() -> new CustomException()) |
需显式处理异常 |
3️⃣ 转换值(避免嵌套)
| 方法 |
说明 |
示例 |
作用 |
Optional<U> map(Function mapper) |
对值应用函数(返回新 Optional) |
optional.map(String::toUpperCase) |
链式调用(如 user.getAddress().getCity()) |
Optional<U> flatMap(Function mapper) |
对值应用返回 Optional 的函数 |
optional.flatMap(User::getAddress) |
值本身是 Optional 时使用 |
4️⃣ 条件处理(无值/有值时操作)
| 方法 |
说明 |
示例 |
作用 |
void ifPresent(Consumer consumer) |
值存在时执行操作 |
optional.ifPresent(name -> System.out.println(name)) |
仅需处理非空场景 |
void ifPresentOrElse(Consumer, Runnable) |
有值执行 Consumer,无值执行 Runnable |
optional.ifPresentOrElse(System.out::println, () -> System.out.println("空值")) |
完整处理空/非空场景 |
Optional<T> filter(Predicate predicate) |
过滤值(不符合条件则变空) |
optional.filter(name -> name.length() > 3) |
验证值是否符合规则 |
传统 vs Optional
场景 1:嵌套对象取值
1 2 3 4 5 6 7 8 9 10 11 12
| String city = "未知"; if (user != null && user.getAddress() != null && user.getAddress().getCity() != null) { city = user.getAddress().getCity().getName(); }
String city = Optional.ofNullable(user) .map(User::getAddress) .map(Address::getCity) .map(City::getName) .orElse("未知");
|
场景 2:从 Map 中安全取值
1 2 3 4 5 6 7 8 9 10 11 12
| Map<String, String> config = new HashMap<>();
String value = null; if (config != null && config.get("timeout") != null) { value = config.get("timeout"); }
String value = Optional.ofNullable(config) .map(map -> map.get("timeout")) .orElse("30s");
|
场景 3:处理数据库查询结果(可能为空)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| User user = userRepository.findById(100); if (user != null) { } else { }
Optional<User> userOpt = userRepository.findById(100); userOpt.ifPresent(user -> { }); userOpt.orElseThrow(() -> new UserNotFoundException("ID 100 不存在"));
|
Optional 使用规则
| 误区 |
正确做法 |
原因 |
❌ 用 Optional 作为类的成员变量 |
✅ 仅用于方法返回值 |
Optional 不可序列化,且违背设计初衷(字段应明确表示是否可空) |
❌ 使用 optional.get() |
✅ 永远用 orElse/orElseGet/orElseThrow |
get() 会抛异常,和直接用 null 无区别 |
❌ 用 Optional 包装集合 |
✅ 集合返回空集合(Collections.emptyList()) |
集合的空值语义应由空集合表示,而非 Optional |
❌ 用 Optional 替代基础类型判断 |
✅ 用基本类型特化版本(OptionalInt/OptionalDouble) |
基本类型包装会损失性能(OptionalInt 无装箱开销) |
💡 关键原则:
Optional 是方法返回值的「语义增强器」,不是 null 的替代品!
- 方法返回
Optional<T> → 明确告诉调用者:「这个值可能为空」
- 方法返回
T → 明确告诉调用者:「这个值一定不为空」
使用事例
正确使用场景
1 2 3 4 5 6 7 8 9 10 11
| public Optional<User> findUserById(int id) { User user = userRepository.findById(id); return Optional.ofNullable(user); }
Optional<User> userOpt = findUserById(100); userOpt.ifPresent(user -> { });
|
链式调用示例
1 2 3 4 5 6 7 8 9 10
| String lang = Optional.ofNullable(config) .map(c -> c.get("language")) .filter(s -> !s.isEmpty()) .orElse("zh-CN");
LocalDateTime time = Optional.ofNullable(order) .map(Order::getModifiedTime) .orElse(LocalDateTime.now());
|
避免过度使用
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class User { private Optional<String> name; }
public class User { private String name;
public Optional<String> getName() { return Optional.ofNullable(name); } }
|
总结
| 传统代码 |
Optional 代码 |
本质差异 |
String name = user.getName(); |
String name = Optional.ofNullable(user).map(User::getName).orElse("Unknown"); |
强制显式处理空值:编译器要求你写 orElse/ifPresent 等,否则无法编译通过 |
if (user != null) { ... } |
userOpt.ifPresent(u -> { ... }); |
代码结构明确:ifPresent 语义清晰,避免嵌套 if |
十二、Java 8+ 新特性详解
1. 日期时间API(java.time)
核心类:
| 类 |
用途 |
示例 |
LocalDate |
日期(年月日) |
LocalDate.now() |
LocalTime |
时间(时分秒) |
LocalTime.of(10, 30) |
LocalDateTime |
日期+时间 |
LocalDateTime.now() |
ZonedDateTime |
带时区的日期时间 |
ZonedDateTime.now(ZoneId.of("Asia/Shanghai")) |
Duration |
时间段(秒/纳秒) |
Duration.between(start, end) |
Period |
日期段(年月日) |
Period.between(date1, date2) |
日期时间格式化:
1 2 3
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); String formatted = now.format(formatter);
|
2. 并发工具类
CompletableFuture:
1 2 3 4
| CompletableFuture.supplyAsync(() -> { return "Result"; }).thenApply(result -> result.toUpperCase()) .thenAccept(System.out::println);
|
StampedLock(读写锁优化):
1 2 3 4 5 6 7
| StampedLock lock = new StampedLock(); long stamp = lock.readLock(); try { } finally { lock.unlockRead(stamp); }
|
十三、JVM性能调优关键点
1. 内存参数配置
| 参数 |
说明 |
示例 |
-Xms |
初始堆大小 |
-Xms512m |
-Xmx |
最大堆大小 |
-Xmx2g |
-XX:NewRatio |
新生代/老年代比例 |
-XX:NewRatio=2 |
-XX:MaxMetaspaceSize |
元空间最大大小 |
-XX:MaxMetaspaceSize=256m |
-XX:+UseG1GC |
启用G1垃圾回收器 |
-XX:+UseG1GC |
2. 常见内存问题诊断
OutOfMemoryError:
- 堆内存溢出:
java.lang.OutOfMemoryError: Java heap space
- 元空间溢出:
java.lang.OutOfMemoryError: Metaspace
- 解决:增大
-XX:MaxMetaspaceSize
- 栈溢出:
java.lang.StackOverflowError
内存泄漏诊断工具:
jmap -heap <pid>:查看堆内存使用
jstat -gc <pid> 1000:实时监控GC情况
jvisualvm:图形化分析内存快照
十四、设计模式的应用
1. 单例模式(双重检查锁)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public 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; } }
|
2. 工厂模式(简单工厂)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public interface Shape { void draw(); }
public class Circle implements Shape { public void draw() { System.out.println("Circle"); } }
public class ShapeFactory { public Shape getShape(String type) { if ("circle".equals(type)) return new Circle(); if ("rectangle".equals(type)) return new Rectangle(); return null; } }
|
3. 观察者模式(Java内置实现)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.util.Observable; import java.util.Observer;
class Subject extends Observable { private int state; public void setState(int state) { this.state = state; setChanged(); notifyObservers(state); } }
class ObserverImpl implements Observer { public void update(Observable o, Object arg) { System.out.println("State changed to: " + arg); } }
|
十五、反射机制深度解析
1. 反射核心API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Class<?> clazz = Class.forName("com.example.MyClass");
Class<?> clazz = MyClass.class;
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("myMethod", String.class); method.invoke(obj, "param");
Field field = clazz.getDeclaredField("privateField"); field.setAccessible(true); field.set(obj, "value");
|
2. 反射应用场景
- 框架开发:Spring IOC依赖注入
- 动态代理:JDK动态代理
- 序列化/反序列化:JSON库(如Jackson)
- 单元测试:访问私有成员
3. 反射性能优化
1 2 3 4 5 6 7 8 9 10
| private static final Method METHOD = MyClass.class.getMethod("method");
MethodHandle handle = MethodHandles.lookup().findVirtual(MyClass.class, "method", MethodType.methodType(void.class)); handle.invokeExact(obj);
VarHandle handle = MethodHandles.lookup().findVarHandle(MyClass.class, "field", int.class); handle.set(obj, 10);
|
十六、JVM内存模型(JMM)
1. 主内存与工作内存
2. 关键内存屏障
| 指令 |
作用 |
使用场景 |
LoadLoad |
确保加载指令顺序 |
读取共享变量前 |
StoreStore |
确保存储指令顺序 |
写入共享变量后 |
LoadStore |
确保加载在存储前完成 |
读写混合操作 |
StoreLoad |
最强屏障,防止重排序 |
volatile写后读 |
3. volatile关键字原理
- 保证可见性:写入时刷新到主内存,读取时从主内存加载
- 禁止指令重排序:通过内存屏障实现
- 不保证原子性:如
i++操作(包含读-改-写三步)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private volatile boolean initialized = false;
void init() { initialized = true; }
void use() { if (initialized) { } }
|
十七、Java并发编程核心
1. synchronized底层原理
- 对象头结构:
1
| [Mark Word][Class Pointer][Lock Record]
|
- 锁升级过程:
- 锁消除(JIT优化):
1 2 3 4 5 6
| public void method() { synchronized(new Object()) { } }
|
2. Lock接口与AQS
- ReentrantLock实现:
1 2 3 4 5 6 7
| Lock lock = new ReentrantLock(); lock.lock(); try { } finally { lock.unlock(); }
|
- AQS(AbstractQueuedSynchronizer)核心:
- 维护一个CLH队列(FIFO)
- 通过CAS操作修改state字段
- 支持公平锁/非公平锁
3. 并发工具类详解
| 类 |
用途 |
示例 |
CountDownLatch |
计数器,等待多个线程完成 |
new CountDownLatch(3) |
CyclicBarrier |
循环屏障,等待固定数量线程 |
new CyclicBarrier(3) |
Semaphore |
信号量,控制并发数 |
new Semaphore(5) |
Exchanger |
线程间数据交换 |
exchanger.exchange(data) |
Phaser |
动态注册的屏障 |
phaser.register() |