多线程问题集锦
一、如何保证 T1→T2→T3 的执行顺序?
要确保 T2 在 T1 完成后执行,T3 在 T2 完成后执行,最直观的方案是使用Thread.join()方法。join()的核心作用是让当前线程阻塞,等待目标线程执行完毕后再继续运行,从而强制线程按顺序执行。
实现示例:
1 | public class ThreadOrder { |
要确保 T2 在 T1 完成后执行,T3 在 T2 完成后执行,最直观的方案是使用Thread.join()方法。join()的核心作用是让当前线程阻塞,等待目标线程执行完毕后再继续运行,从而强制线程按顺序执行。
1 | public class ThreadOrder { |
注解(Annotation)是 Java 5 引入的一种元数据(metadata)机制,用于为代码添加额外信息(如配置、约束、说明等),不直接影响代码逻辑,但可通过工具(编译器、框架)解析并产生实际作用(如编译检查、代码生成)。本文将从基础概念、元注解、注解处理器等方面全面解析 Java 注解。
注解是一种特殊的 “标记”,可附加在类、方法、字段等程序元素上,格式为 @注解名(属性=值)。例如:
1 | // 方法上的@Override注解(标记方法重写) |
@Override 确保方法正确重写父类方法,编译器会校验正确性。@Data 自动生成 getter/setter 方法,减少模板代码。@Autowired 实现依赖注入,框架在运行时通过反射解析注解。@Deprecated 标记过时元素,javadoc 会包含该信息。元注解(Meta Annotation)是用于修饰 “注解” 的注解,定义了注解的适用范围、生命周期、继承性等基本特性。Java 内置了 5 种元注解:
@Target:指定注解的适用位置用于限制注解可附加的程序元素(如类、方法、字段等),属性为 ElementType 数组,常见取值:
ElementType 取值 |
含义 | 示例 |
|---|---|---|
TYPE |
类、接口、枚举 | @Service 用于类 |
METHOD |
方法 | @Override 用于方法 |
FIELD |
字段(成员变量) | @Autowired 用于字段 |
PARAMETER |
方法参数 | @RequestParam 用于参数 |
CONSTRUCTOR |
构造器 | 自定义注解用于构造器 |
LOCAL_VARIABLE |
局部变量 | 较少使用 |
ANNOTATION_TYPE |
注解类型本身 | 元注解修饰其他注解 |
PACKAGE |
包 | 用于包信息配置 |
TYPE_PARAMETER(Java 8+) |
类型参数(如泛型 <T>) |
@NonNull <T> T get() |
TYPE_USE(Java 8+) |
任何类型使用处(如变量声明) | List<@NonNull String> |
非线性结构是指数据元素之间存在一对多或多对多关系的结构,无法用线性序列完整描述。常见的非线性结构包括树(一对多)和图(多对多),它们广泛应用于层次关系建模(如文件系统)、网络关系描述(如社交网络)等场景。
树是一种具有层次关系的非线性结构,核心特征是存在一个根节点,其余节点分属不同子树,形成一对多的分支关系。
树是由 n(n ≥ 0) 个节点组成的有限集合:
n = 0 时,称为空树。n > 0 时,有且仅有一个根节点(无前驱节点);其余节点可分为若干个互不相交的子集,每个子集本身也是一棵树(称为子树)。核心特征:
在 Java 中,时间操作是日常开发的常见需求,包括获取当前时间、格式化时间、计算时间差等。随着 Java 版本的演进,时间 API 也从早期的 Date、Calendar 发展到 Java 8 引入的 java.time 系列(如 LocalDateTime、ZonedDateTime),后者解决了传统 API 的线程不安全、设计混乱等问题。本文将全面介绍 Java 中操作时间的主要方式及最佳实践。
java.util.DateDate 是最早期的时间类,存储自 1970 年 1 月 1 日 00:00:00(UTC)以来的毫秒数,但大部分方法已被废弃(如 getYear()、getMonth()),仅保留少数核心方法(如 getTime())。
Date 对象1 | import java.util.Date; |
线性结构是数据结构中最基础也最常用的一类,其核心特征是数据元素之间存在一对一的线性关系。常见的线性结构包括线性表(顺序表、链表)、队列、栈等。它们在逻辑上形成一条 “直线”,每个元素(除首尾外)有唯一的前驱和后继。
线性结构的元素间关系可概括为:
这种结构使得数据的遍历可以按线性顺序依次进行(如从首到尾)。
线性表是由零个或多个数据元素组成的有限序列,是线性结构的抽象模型。根据存储方式的不同,线性表可分为顺序表(顺序存储)和链表(链式存储)。
顺序表是用连续的存储空间存储元素的线性表,逻辑上的顺序与物理存储顺序一致(类似数组)。
size)≤ 容量(capacity)。| 操作 | 实现逻辑 | 时间复杂度 |
|---|---|---|
| 访问(get) | 通过下标直接定位元素 | O(1) |
| 插入(add) | 若插入中间位置,需移动后续元素腾出空间 | O(n) |
| 删除(remove) | 若删除中间元素,需移动后续元素填补空位 | O(n) |
| 扩容(ensureCapacity) | 复制原数组到更大的新数组 | O (n)(触发时) |