在多线程的情况下 有可能创建出多个实例对象
可以用线程同步的方法去处理 比如把方法声明为synchronized
123456789101112131415161718192021222324252627282930313233public class Test3 { public static void main(String[] args) throws InterruptedException { System.out.println("猪百万"); Cat c1 = Cat.getCatInstance(); Cat c2 = Cat.getCatInstance(); System.out.println(c1==c2); //true c1.catchMouse(); c2.catchMouse(); }}class Cat{ private Cat(){ } private static Cat cat; public synchronized s ...
Collections.synchronizedXXX 是 Java 集合框架中用于将非线程安全的集合转换为线程安全集合的工具方法,主要作用是通过 同步机制 保证多线程环境下集合操作的安全性。以下是对这类方法的总结:
1. 核心功能
线程安全转换:将非线程安全的集合(如 ArrayList、HashMap、HashSet 等)包装为线程安全的版本,避免多线程并发操作时出现数据不一致或异常(如 ConcurrentModificationException)。
同步实现方式:通过 包装器模式,在原集合的所有方法(如 add、remove、get 等)外层添加 synchronized 同步块,确保同一时刻只有一个线程能执行集合的方法。
2. 常用方法及对应集合
方法
作用
对应的非线程安全集合
线程安全包装后的类型
synchronizedList(List<T>)
将 List 转换为线程安全集合
ArrayList、LinkedList
同步化的 List
synchronizedSet(Set<T>)
将 Set 转换为线程安全集合
Hash ...
一、基本概念生产者 - 消费者问题是多线程同步与通信的经典案例。存在两类线程:
生产者线程:负责生成数据,将数据放入共享缓冲区。
消费者线程:负责从共享缓冲区取出数据并进行处理。
共享缓冲区作为两者传递数据的中介,需保证操作线程安全。
二、核心问题(一)线程同步多个线程(生产者和消费者)同时操作共享缓冲区时,要保证操作原子性,避免数据不一致。比如生产者添加数据时,消费者不能同时取数据;生产者修改数据过程中,消费者不能读 “半成品” 数据。
(二)线程通信
缓冲区满时,生产者应等待,直到消费者取出数据腾出空间。
缓冲区空时,消费者应等待,直到生产者放入数据。
三、解决方案(一)同步机制(以 synchronized 为例)通过给共享资源(如案例中的 Queue 对象)加锁,保证同一时间只有一个线程能操作它,解决线程同步问题。例如代码中用 synchronized (q) 确保生产者修改数据和消费者读取数据的操作互斥,避免数据不一致。
(二)等待 - 通知机制(wait() 和 notify()/notifyAll())
wait():使当前线程进入等待状态,释放对 ...
一、死锁问题1. 死锁的定义死锁是指两个或多个线程相互持有对方所需的资源,且彼此都不释放已持有的资源,导致所有线程永久阻塞的状态。
2. 死锁产生的必要条件
互斥条件:资源只能被一个线程持有(不可共享)。
持有并等待:线程持有部分资源,同时等待其他资源。
不可剥夺:资源不能被强制剥夺,只能由持有线程主动释放。
循环等待:线程间形成环形等待链(T1 等待 T2 的资源,T2 等待 T1 的资源)。
3. 死锁示例(Java 代码)java
运行
12345678910111213141516171819202122232425262728293031323334353637383940public class DeadlockExample { // 定义两个资源 private static final Object resource1 = new Object(); private static final Object resource2 = new Object(); public static void main(String[] args) ...
一、概念与分类
前台线程(用户线程)
定义:默认创建的线程类型,负责核心业务逻辑,是程序运行的主体。
特点:JVM 必须等待所有前台线程执行完毕才会退出,即使主线程结束,其他前台线程仍可继续运行。
后台线程(守护线程 / Daemon Thread)
定义:为前台线程提供服务的辅助线程(如日志、监控、垃圾回收等)。
特点:依赖前台线程存在,当所有前台线程结束后,JVM 会强制终止所有后台线程,无需等待其执行完毕。
二、核心区别
对比项
前台线程
后台线程
默认类型
是(创建后默认为此类型)
否(需显式设置)
JVM 退出条件
等待所有前台线程执行完毕
随最后一个前台线程结束而终止
作用
执行核心业务逻辑
提供辅助服务
三、后台线程的设置与注意事项
设置方法
调用 Thread 类的 setDaemon(boolean on) 方法,参数为 true 时设置为后台线程。
示例:
123Thread daemonThread = new Thread(() -> { ... });daemonThread.se ...
,其中隔离级别(Isolation Level) 是控制多个并发事务之间数据可见性的关键属性。它决定了一个事务可能受到其他并发事务影响的程度。
一、事务隔离级别的定义事务隔离级别是数据库为了处理并发访问而设计的规则,用于平衡数据一致性和并发性能。Spring 通过@Transactional的isolation属性指定隔离级别,其值对应数据库的标准隔离级别。
二、Spring 支持的隔离级别(枚举:Isolation)Spring 定义了 5 种隔离级别,对应数据库的 SQL 标准:
DEFAULT(默认)
含义:使用数据库默认的隔离级别(大多数数据库默认是READ_COMMITTED,如 MySQL、SQL Server)。
使用场景:大多数情况下的默认选择,无需显式指定。
READ_UNCOMMITTED(读未提交)
含义:一个事务可以读取另一个未提交事务的数据。
问题:可能出现脏读(读取到未提交的无效数据)。
性能:最高(并发能力强),但一致性最低。
READ_COMMITTED(读已提交)
含义:一个事务只能读取另一个已提交事务的数据。
解决:避免脏读,但可能出 ...
事务传播行为(Propagation)定义了多个事务方法相互调用时,事务的创建、嵌套、隔离规则,核心解决 “方法调用时事务如何联动” 的问题。以下是 7 种传播行为及其特性的总结:
1. REQUIRED(默认值)
特性:如果当前有事务,就加入该事务;如果没有,就新建一个事务。
核心:“随大流”,所有操作合并到同一事务中,要么一起成功,要么一起回滚。
场景:大多数业务场景(如订单创建时同时扣库存、减余额)。
2. SUPPORTS
特性:如果当前有事务,就加入;如果没有,就以非事务方式执行(不开启事务)。
核心:“可选事务”,有无事务均可,不主动创建事务。
场景:查询操作(如订单详情查询,有事务则参与,无则直接执行)。
3. MANDATORY
特性:必须在已存在的事务中执行;如果当前没有事务,直接抛异常。
核心:“强制依赖”,自己不创建事务,必须依赖上层调用者的事务。
场景:核心操作(如资金扣减,必须在调用者的事务中执行,防止无事务时数据错乱)。
4. REQUIRES_NEW
特性:无论当前是否有事务,都新建一个独立事务;若当前有事务,则先暂停原事务,新事务执行完再恢复。
核 ...
在 Spring 框架中,@Transactional注解用于声明事务管理一、事务管理器的原理1、事务管理器(transactionManager)
作用:控制事务的获取、提交、回滚。
底层默认:JdbcTransactionManager。
2、原理
事务管理器(TransactionManager):控制事务的提交和回滚。
事务拦截器(TransactionInterceptor):控制事务何时提交和回滚。
回滚触发:completeTransactionAfterThrowing(txInfo, ex)(方法执行出现异常时,执行回滚)。
提交触发:commitTransactionAfterReturning(txInfo)(方法正常返回时,执行提交)。
二、timeout
timeout(同 timeoutString):超时时间,事务超时,秒为单位;
一旦超过约定时间,事务就会回滚。超时时间是指:从方法开始,到最后一次据库操作结束的时间。写法可以是:
@Transactional(timeout = 3)
@Transactional(timeoutSt ...
1. x == y(引用比较)
本质:比较两个数组变量的内存地址是否相同
核心逻辑:判断是否指向内存中同一个数组对象
适用场景:检查两个数组变量是否引用同一个实例
示例:
123456int[] a = {1,2,3};int[] b = a; // 指向同一对象int[] c = {1,2,3};// 新对象,内容相同但地址不同a == b → truea == c → false
特点:与数组类型无关,仅关注引用是否相同
2. x.equals (y)(数组对象的 equals 方法)
本质:继承自 Object 类的 equals 方法,等价于 x == y
核心逻辑:同样比较引用地址,而非数组内容
适用场景:同 x == y,无实际额外价值
示例:
12a.equals(b) → true(同x == y)a.equals(c) → false(同x == y)
特点:数组未重写 equals 方法,行为与 == 完全一致 ...
一、Collections 工具类(操作集合)1. 排序相关
sort(List<T> list):对 List 按自然排序(元素需实现 Comparable 接口)
sort(List<T> list, Comparator<? super T> c):按自定义比较器排序 List
2. 查找与最值
binarySearch(List<? extends Comparable<? super T>> list, T key):二分查找元素(需先排序)
max(Collection<? extends T> coll):获取集合中自然排序的最大元素
min(Collection<? extends T> coll):获取集合中自然排序的最小元素
3. 集合操作
reverse(List<?> list):反转 List 中元素顺序
shuffle(List<?> list):随机打乱 List 元素
fill(List<? super T> list, T obj ...



