在Java中,线程阻塞方法主要用于控制线程的执行流程,常见方法及示例如下:
1. 推荐阻塞方法
(1) Thread.sleep()
实现方式:让当前线程暂停执行指定时间。
使用场景:需要短暂延迟(如轮询、模拟耗时操作)。
示例代码:
public class SleepExample {
public static void main(String[] args) {
try {
System.out.println("Start sleeping...");
Thread.sleep(2000); // 暂停2秒
System.out.println("Woke up!");
} catch (InterruptedException e) {
System.out.println("Sleep interrupted!");
}
}
}
备注:
不释放锁:在同步块中调用sleep()不会释放对象锁。可中断:InterruptedException需处理,线程中断会强制唤醒。
(2) Object.wait()
实现方式:释放对象锁并进入等待状态,需其他线程调用notify()或notifyAll()唤醒。
使用场景:线程间协作(如生产者-消费者模式)。
示例代码:
public class WaitNotifyExample {
private static final Object lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock) {
System.out.println("Thread A is waiting...");
try {
lock.wait(); // 释放锁并等待
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread A woke up!");
}
}).start();
new Thread(() -> {
synchronized (lock) {
System.out.println("Thread B is notifying...");
lock.notify(); // 唤醒等待线程
}
}).start();
}
}
备注:
必须在同步块中调用,否则抛IllegalMonitorStateException。释放锁:等待时释放对象锁,允许其他线程访问同步代码块。
(3) Thread.join()
实现方式:等待另一个线程执行完毕后再继续当前线程。
使用场景:需等待其他线程完成后再执行后续操作。
示例代码:
public class JoinExample {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
System.out.println("Thread A is running...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
Thread threadB = new Thread(() -> {
System.out.println("Thread B is running...");
});
threadA.start();
threadB.start();
try {
threadA.join(); // 等待threadA结束
System.out.println("threadA has finished.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
备注:
阻塞当前线程:调用join()的线程(如主线程)会被阻塞,直到目标线程结束。可指定超时时间:join(long millis)可设置最长等待时间。
(4) LockSupport.park()
实现方式:通过LockSupport工具类实现更灵活的阻塞与唤醒。
使用场景:高级线程协作(如线程池实现)。
示例代码:
import java.util.concurrent.locks.LockSupport;
public class ParkExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("Thread is parking...");
LockSupport.park(); // 阻塞当前线程
System.out.println("Thread un-parked!");
});
thread.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
LockSupport.unpark(thread); // 唤醒线程
}
}
备注:
无需锁:park()和unpark()不依赖对象锁,适合复杂场景。线程关联:unpark()需指定目标线程。
2. 不推荐方法
Thread.yield()
实现方式:让出当前时间片,让其他同优先级线程运行。
使用场景:极少使用,因行为依赖JVM调度。
示例代码:
public class YieldExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread is running...");
Thread.yield();
}
});
thread.start();
}
}
备注:
不保证阻塞:仅建议JVM切换线程,实际效果不可控。适用性差:通常无需显式调用。
方法对比表格
方法实现方式使用场景优点缺点Thread.sleep()暂停当前线程指定时间简单延迟、模拟耗时操作实现简单,直接控制时间不释放锁,可能阻塞资源Object.wait()释放锁并等待唤醒线程间协作(如生产者-消费者)灵活控制线程唤醒,支持多线程通信需配合synchronized使用Thread.join()等待其他线程完成线程依赖关系处理确保线程顺序执行阻塞当前线程,需谨慎使用LockSupport.park()灵活阻塞与唤醒高级协作(如线程池)无需锁,更灵活需手动管理线程关联Thread.yield()让出时间片不推荐,仅用于调试低开销行为不可预测,依赖JVM实现
总结建议
优先使用:sleep()(简单延迟)、wait()/notify()(线程协作)、join()(线程依赖)。避免滥用:yield()因行为不可控,Thread.stop()等已弃用方法需彻底避免。关键点:
wait()和synchronized必须配合使用。join()会阻塞调用线程,需合理设计线程依赖关系。LockSupport适合高级场景,需理解其底层机制。