Java中的wait()和Thread:深入解析与实践
简介
在Java多线程编程中,wait()
和 Thread
是两个至关重要的概念。Thread
类是Java中线程的基础,用于创建和管理线程。而 wait()
方法则是用于线程间通信的关键机制,它允许线程暂停执行,直到其他线程调用该对象的 notify()
或 notifyAll()
方法。深入理解这两个概念对于编写高效、可靠的多线程程序至关重要。
目录
- 基础概念
- Thread类
- wait() 方法
- 使用方法
- 创建和启动线程
- 使用wait() 进行线程通信
- 常见实践
- 生产者 - 消费者模式
- 线程同步
- 最佳实践
- 避免死锁
- 合理使用wait() 和 notify()
- 小结
- 参考资料
基础概念
Thread类
Thread
类是Java中所有线程的父类。每个线程都是 Thread
类的实例,或者是其子类的实例。通过创建 Thread
类的实例,可以定义和控制线程的行为。
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("This is a new thread running.");
}
}
wait() 方法
wait()
方法是定义在 Object
类中的方法,这意味着所有Java对象都具有该方法。当一个线程调用某个对象的 wait()
方法时,该线程会释放对象的锁,并进入等待状态,直到其他线程调用该对象的 notify()
或 notifyAll()
方法。
public class WaitExample {
public static void main(String[] args) {
Object lock = new Object();
Thread thread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread is about to wait.");
lock.wait();
System.out.println("Thread has been notified.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock) {
System.out.println("Main thread is notifying the waiting thread.");
lock.notify();
}
}
}
使用方法
创建和启动线程
创建线程有两种常见方式:继承 Thread
类或实现 Runnable
接口。
继承Thread类
public class ThreadExample extends Thread {
@Override
public void run() {
System.out.println("Thread created by extending Thread class is running.");
}
public static void main(String[] args) {
ThreadExample thread = new ThreadExample();
thread.start();
}
}
实现Runnable接口
public class RunnableExample implements Runnable {
@Override
public void run() {
System.out.println("Thread created by implementing Runnable interface is running.");
}
public static void main(String[] args) {
Runnable runnable = new RunnableExample();
Thread thread = new Thread(runnable);
thread.start();
}
}
使用wait() 进行线程通信
wait()
方法通常与 synchronized
块结合使用,以确保线程安全。
public class ProducerConsumer {
private int sharedResource = 0;
private boolean available = false;
public synchronized void produce(int value) {
while (available) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
sharedResource = value;
available = true;
System.out.println("Produced: " + sharedResource);
notify();
}
public synchronized int consume() {
while (!available) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
available = false;
System.out.println("Consumed: " + sharedResource);
notify();
return sharedResource;
}
}
常见实践
生产者 - 消费者模式
生产者 - 消费者模式是多线程编程中的经典模式,通过 wait()
和 notify()
方法实现线程间的协作。
public class Producer implements Runnable {
private ProducerConsumer pc;
public Producer(ProducerConsumer pc) {
this.pc = pc;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
pc.produce(i);
}
}
}
public class Consumer implements Runnable {
private ProducerConsumer pc;
public Consumer(ProducerConsumer pc) {
this.pc = pc;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
pc.consume();
}
}
}
public class Main {
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer();
Thread producerThread = new Thread(new Producer(pc));
Thread consumerThread = new Thread(new Consumer(pc));
producerThread.start();
consumerThread.start();
}
}
线程同步
wait()
和 notify()
方法常用于实现线程同步,确保多个线程在访问共享资源时的正确性。
public class SynchronizationExample {
private static int counter = 0;
private static final Object lock = new Object();
public static void increment() {
synchronized (lock) {
counter++;
}
}
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final counter value: " + counter);
}
}
最佳实践
避免死锁
死锁是多线程编程中常见的问题,发生在两个或多个线程相互等待对方释放资源时。为避免死锁,应遵循以下原则: - 尽量减少锁的使用范围。 - 按照相同顺序获取锁。 - 避免在锁内执行长时间操作。
合理使用wait() 和 notify()
- 使用
wait()
时,应始终在while
循环中检查条件,以避免虚假唤醒。 - 调用
notify()
或notifyAll()
时,确保线程处于正确的状态。
小结
Thread
类和 wait()
方法是Java多线程编程中的核心概念。通过合理使用它们,可以实现线程的创建、管理和通信,从而编写高效、可靠的多线程程序。在实际应用中,需要注意避免死锁等问题,并遵循最佳实践,以确保程序的正确性和性能。
参考资料
- Oracle Java Documentation
- 《Effective Java》by Joshua Bloch
- 《Java Concurrency in Practice》by Brian Goetz