在Java编程中,线程的等待和同步是处理并发问题的关键。线程等待可以让一个线程暂停执行,直到某个条件成立或者另一个线程执行了特定的操作。以下是Java中实现线程等待的几种常见场景和方法的详细介绍。
一、使用wait()方法
wait()方法是Object类中的一个方法,它允许一个线程暂停执行,直到当前对象被通知(即调用了该对象的notify()或notifyAll()方法)。以下是一个使用wait()方法的简单例子:
public class WaitExample {
public static void main(String[] args) {
Object lock = new Object();
Thread producer = new Thread(new Producer(lock));
Thread consumer = new Thread(new Consumer(lock));
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
private Object lock;
public Producer(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("Producer is producing...");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer has been notified.");
}
}
}
class Consumer implements Runnable {
private Object lock;
public Consumer(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("Consumer is consuming...");
lock.notify();
}
}
}
在这个例子中,Producer线程在执行完毕后调用wait()方法,这将导致它暂停执行,直到Consumer线程调用notify()方法。
二、使用wait(long timeout)和notifyAll()方法
wait(long timeout)方法允许线程在指定的时间内等待。如果超时或线程被通知,线程将恢复执行。notifyAll()方法会唤醒所有等待该对象的线程。以下是一个使用这些方法的例子:
synchronized (lock) {
try {
lock.wait(1000); // 等待最多1000毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notifyAll(); // 唤醒所有等待的线程
}
三、使用CountDownLatch
CountDownLatch是一个同步辅助类,允许一个或多个线程等待一组事件发生。以下是一个使用CountDownLatch的例子:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(5); // 线程总数为5
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is running...");
latch.await(); // 等待事件发生
System.out.println(Thread.currentThread().getName() + " has been notified.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
Thread.sleep(1000); // 主线程等待一段时间,让其他线程运行
latch.countDown(); // 事件发生,计数减1
}
}
在这个例子中,5个线程将等待主线程调用latch.countDown()方法。
四、使用CyclicBarrier
CyclicBarrier是一个同步辅助类,它允许一组线程在到达某个点时被阻塞,直到所有线程都到达这个点。以下是一个使用CyclicBarrier的例子:
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println("All threads have reached the barrier.");
}
});
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is waiting at the barrier...");
barrier.await(); // 等待所有线程到达
System.out.println(Thread.currentThread().getName() + " has reached the barrier.");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
在这个例子中,5个线程将在到达CyclicBarrier的await()方法处等待,直到所有线程都到达,然后执行Runnable对象中的代码。
总结
以上介绍了Java中处理线程等待的几种常见方法。在实际应用中,根据具体需求选择合适的方法至关重要。掌握这些方法可以帮助你更好地处理并发问题,提高程序的效率和稳定性。
