Java多线程核心方法详解:start、run、join与守护线程实战
本文详解Java多线程开发中Thread类的核心方法,包括启动线程的start与run区别、控制执行的yield与sleep、协调关系的join、中断机制interrupt、守护线程daemon以及优先级priority,配合代码示例展示各方法在实际场景中的应用与注意事项。
启动线程的基础:start 与 run
在Java中,创建并启动线程最常见的误区是直接调用 run() 方法。理解 start() 和 run() 的本质区别是掌握多线程的第一步。
第1步:使用 start() 正式开启线程
目的:正确启动新线程,使线程进入可运行状态,由操作系统调度执行。
原理说明:
start()是synchronized同步方法,确保线程只能被启动一次。如果多次调用会抛出IllegalThreadStateException。- 它内部调用本地方法
start0()(底层C++实现),由JVM创建新的OS线程。 - 线程启动后,会自动调用该线程对象的
run()方法。
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
private native void start0();第2步:编写 run() 作为任务逻辑体
目的:定义线程实际需要执行的业务逻辑。
关键点:
run()只是普通的方法覆盖,如果在主线程中直接调用t.run(),代码将在当前线程顺序执行,不会开启新线程。- 只有当线程处于“新建”状态并通过
start()触发时,JVM才会在新线程上下文中执行run()。
线程控制与协调方法
第3步:yield() 主动让出CPU资源
作用:提示调度器当前线程愿意让出剩余的时间片,从“运行状态”退回到“就绪状态”,等待重新调度。
特点:
- 是静态方法,仅对同优先级或更高优先级的线程有效。
- 如果系统中没有其他同级或更高级别的线程准备运行,当前线程可能继续执行。
- 不具有强制性,具体让给谁由系统决定,不建议用于关键逻辑控制。
public static native void yield();
第4步:join() 实现线程合并(串行化)
作用:在当前线程中调用另一个线程的 join() 方法,将导致当前线程暂停,直到目标线程执行完毕。
应用场景:需要等待子线程完成某些预处理才能进行后续业务,即“线程插队”。它将并行逻辑强制转为串行。
public class ThreadMethod02 {
public static void main(String[] args) throws InterruptedException {
T2 t2 = new T2();
t2.start();
//主线程打印
int count = 0;
for (int i = 1; i <= 10; i++) {
Thread.sleep(1000);
System.out.println("main" + i);
if (++count == 5) {
t2.join();//主线程在此处阻塞,等待t2执行完
}
}
}
}
class T2 extends Thread {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A" + i);
}
}
}
第5步:sleep() 暂停当前线程
作用:使当前正在执行的线程进入“阻塞状态”指定的时间,期间让出CPU使用权但不释放锁。
sleep(long millis):毫秒级休眠。sleep(long millis, int nanos):纳秒级高精度休眠。
注意:睡眠可以被其他线程通过 interrupt() 打断,此时会抛出 InterruptedException。
线程中断与生命周期管理
第6步:interrupt() 发送中断信号
作用:标记线程为“中断状态”,并非强制杀死线程。
机制:
- 如果目标线程正处于阻塞状态(如调用了
sleep,wait,join),调用interrupt()会立即清除中断标志并抛出InterruptedException,线程需捕获异常处理退出逻辑。 - 如果目标线程处于运行状态,中断标志会被设置为true,线程继续执行,直到下一次调用阻塞方法时检测标志并做出反应。
public class ThreadMethod03 {
public static void main(String[] args) throws InterruptedException {
T3 t3 = new T3();
t3.start();
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName());
}
t3.interrupt();//向子线程发送中断信号
}
}
class T3 extends Thread {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println("A");
}
try {
System.out.println("进行休眠");
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "被Interrupted!!!");
// 通常在此处处理清理工作或退出循环
}
}
}
第7步:daemon 守护线程设置
定义:Java线程分用户线程(User Thread)和守护线程(Daemon Thread)。守护线程用于服务后台任务(如垃圾回收),当所有用户线程结束时,JVM会自动退出,无论守护线程是否在运行。
操作方法:
setDaemon(true):必须在start()之前调用,否则抛出IllegalThreadStateException。isDaemon():判断当前是否为守护线程。
public class ThreadMethod04 {
public static void main(String[] args) throws InterruptedException {
T4 t4 = new T4();
t4.setDaemon(true);//必须在start前设置
t4.start();
if (t4.isDaemon()) {
System.out.println("子线程是守护线程");
}
//主线程执行5秒后结束,子线程随之终止
for (int i = 1; i <= 5; i++) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + i);
}
}
}
class T4 extends Thread {
@Override
public void run() {
while (true) { //无限循环
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
}结果现象:当主线程(用户线程)结束后,JVM进程退出,T4守护线程即使未执行完毕也会立即停止。
第8步:Priority 线程优先级管理
范围:最小值1 (MIN_PRIORITY),默认5 (NORM_PRIORITY),最大值10 (MAX_PRIORITY)。
特性:
- 优先级仅影响线程调度概率,不保证高优先级一定先于低优先级执行,最终取决于操作系统调度算法。
- 跨平台风险:不同OS支持的优先级数量不同,过度依赖优先级可能导致移植性问题。
public final static int MIN_PRIORITY = 1; public final static int NORM_PRIORITY = 5; public final static int MAX_PRIORITY = 10;
public class ThreadMethod05 {
public static void main(String[] args) {
T5 t5 = new T5();
t5.setPriority(10);
int priority = t5.getPriority();
System.out.println(priority); // 输出 10
}
}
class T5 extends Thread {
@Override
public void run() {
System.out.println("High Priority Thread Running");
}
}
总结
掌握Java多线程的核心在于理解线程状态的流转与各方法的副作用。start负责创建新线程,run承载逻辑;sleep和yieid用于让步,但前者释放CPU而后者可能重入;join用于线程间同步等待;interrupt是实现优雅退出的关键信号;daemon则适用于无感知的后台服务。合理组合这些方法,才能编写出健壮的多线程应用。以上就是Java多线程方法详细内容的资料,更多关于Java并发编程的技术指南请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













