多线程基础概念
线程与进程:介绍了线程和进程的区别与联系 ,多线程可提升程序执行效率,但也引入线程安全、异常抛出等稳定性问题。
-创建线程方式
- 继承Thread类:重写run方法,通过start启动线程。例如定义类继承Thread,重写run方法实现具体逻辑,再调用start启动。
- 实现Runnable接口:编写run方法,搭配Thread实例启动。如创建实现Runnable接口的类,在run方法写任务逻辑,用Thread包裹启动。
- 匿名内部类(继承Thread或实现Runnable ):方便临时创建线程。像用匿名内部类继承Thread或实现Runnable接口,直接在内部编写逻辑。
- lambda表达式(推荐):简洁创建线程,如 Thread t = new Thread(() -> { /* 线程逻辑 */ }); 。
Thread类常用属性和方法
- 属性:如优先级(设置优先级不一定明显改变运行效果,因线程调度由操作系统完成 )、后台/前台线程(后台线程不阻止进程结束,前台线程会阻止,默认创建的线程是前台 )。
- 方法
- start:真正启动线程,执行后线程自动执行run方法。一个线程对象只能start一次,多次调用会抛 IllegalThreadStateException 。
- currentThread:静态方法,返回调用该方法的线程对象引用。
- interrupt:修改线程内部标志位为true,用于中断线程。处于sleep状态的线程被interrupt会提前唤醒并抛出 InterruptedException ,唤醒后标志位会重置为false。
- isInterrupted:判断线程是否被中断。
- join:让一个线程等待另一个线程结束。例如 main 线程调用 thread.join() , main 线程会等待 thread 线程执行完再继续。join有重载版本,可指定等待时间,超时则不再等待。
- sleep:使线程休眠,进入“阻塞”状态,不参与CPU调度,时间到后恢复就绪状态参与调度。实际开发中常用于测试代码,不过随意添加sleep来优化代码不是好做法。
线程状态
- NEW:线程创建但未start。
- RUNNABLE:可运行状态,获取CPU资源就能执行,代码中未触发阻塞操作时处于此状态。
- BLOCKED:因“加锁”产生的阻塞状态。
- WAITING:无限时等待,如调用无参数join等。
- TIMED_WAITING:有限时等待,如调用有参数join、sleep等。
- TERMINATED:线程执行完(入口方法执行结束 )。
线程安全问题
以 count++ 操作为例,其本质对应load(从内存加载值到CPU寄存器 )、add(在寄存器中执行加操作 )、save(将寄存器值写回内存 )三个CPU指令。多线程环境下,若线程调度不合理,不同线程交叉执行这些指令,会导致数据竞争,使最终结果非预期值,出现线程安全问题 。比如两个线程同时对 count 进行自增,预期结果可能是增加2,但实际可能小于2 。
总结
讲解Java多线程知识,从基础创建方式、常用属性方法,到线程状态转换,再深入到线程安全核心问题。理解这些内容,有助于开发者在Java多线程编程时,正确创建和管理线程,合理处理线程间协作与同步,规避线程安全风险,编写出高效、稳定的多线程程序。