参考小林coding Home
线程安全在三个方面的体现
- 原子性:一个或一组操作要么全部执行成功,要么全部不执行
- 一致性:多个线程访问共享变量,保证所有线程看到的值是一致的。
- 有序性:程序必须按照代码顺序执行
线程创建的方式
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口与FutureTask
- 使用线程池
Java线程的状态
NEW:尚未启动的线程状态
RUNNABLE:就绪状态+正在运行状态
BLOCKED:阻塞状态
WAITING:等待状态的线程正在等待另一线程执行特定的操作
TIMED_WAITING:具有制定等待时间的等待状态
TERMINATED:线程完成执行,终止状态
线程状态转换
如何停止一个线程
使用方法interrupt()来停止线程。
interrupt不会强制线程立即停止,而是通知这个线程停止,何时停止的决定权在线程本身。
对于休眠,阻塞状态的线程,调用interrupt()*会抛出异常,并设置中断标志位为false。为什么要这样设计? 因为底层休眠或阻塞方法实现通常包含循环检测和等待, 它们每次循环都会检测中断标志。如果你不清除,会导致不停地抛出异常。*
所以使用interrupt()停止线程的最佳实践是,抛出异常时设置中断标志位为false,在处理异常时恢复为true,这样既避免了死循环,也保证了中断状态不会丢失。
下面是代码例子
package org.example.throwable;
public class Worker extends Thread{
@Override
public void run() {
try {
while (true) {
System.out.println("线程正在工作");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
// 恢复中断状态
Thread.currentThread().interrupt();
}
// 后续代码可以检测中断标志,执行清理
if (Thread.currentThread().isInterrupted()) {
System.out.println("检测到中断状态,执行清理工作");
}
System.out.println("线程退出");
}
}
sleep和wait的区别
对比例表:
特性 | sleep() | wait() |
---|---|---|
所属类 | Thread 类(静态方法) | Object 类(实例方法) |
锁释放 | ❌ | ✅ |
使用前提 | 任意位置调用 | 必须在同步块内(持有锁) |
唤醒机制 | 超时自动恢复 | 需 notify() /notifyAll() 或超时 |
设计用途 | 暂停线程执行,不涉及锁协作 | 线程间协调,释放锁让其他线程工作 |
- 所属分类的不同:sleep 是
Thread
类的静态方法,可以在任何地方直接通过Thread.sleep()
调用,无需依赖对象实例。wait 是Object
类的实例方法,这意味着必须通过对象实例来调用。 - 锁释放的情况:
Thread.sleep()
在调用时,线程会暂停执行指定的时间,但不会释放持有的对象锁。也就是说,在sleep
期间,其他线程无法获得该线程持有的锁。Object.wait()
:调用该方法时,线程会释放持有的对象锁,进入等待状态,直到其他线程调用相同对象的notify()
或notifyAll()
方法唤醒它 - 使用条件:sleep 可在任意位置调用,无需事先获取锁。 wait 必须在同步块或同步方法内调用(即线程需持有该对象的锁),否则抛出
IllegalMonitorStateException
。 - 唤醒机制:sleep 休眠时间结束后,线程 自动恢复 到就绪状态,等待CPU调度。wait 需要其他线程调用相同对象的
notify()
或notifyAll()
方法才能被唤醒。notify()
会随机唤醒一个在该对象上等待的线程,而notifyAll()
会唤醒所有在该对象上等待的线程。
blocked和wait区别
blocked是锁竞争失败后被动触发的状态,wait是人为触发的主动状态。
blocked的唤醒是自动出发的,wait的唤醒需要用特定方法主动唤醒。
blocked开销会比waitng大,因为blocked抢锁失败了,cpu会不断尝试获取锁。
而wait是自己放弃执行并挂起,操作系统会将它移出运行队列,减少调度。
wait状态下的线程怎么切换到running状态
使用notify或者notifyAll
notify是随机唤醒一个调用了wait()线程
notifyAll是唤醒当前等待队列中所有因调用wait()而等待的线程