Java中等待执行的方法及技巧

在Java编程中,有时候我们需要让某个线程等待,直到某个条件满足或者某个事件发生,这可以通过多种方式实现,以下是一些常用的方法和技术。
使用Thread.sleep()
Thread.sleep(long millis)是Thread类中的一个静态方法,它可以使当前线程暂停执行指定的毫秒数,这是一个简单的等待执行的方法,但需要注意以下几点:
- 阻塞当前线程:调用
Thread.sleep()的线程会暂停执行,直到指定的毫秒数过去。 - 异常处理:如果在睡眠期间发生中断,则
InterruptedException将被抛出,需要捕获此异常并适当处理。
public class SleepExample {
public static void main(String[] args) {
try {
System.out.println("Thread is sleeping...");
Thread.sleep(2000); // 暂停2秒
System.out.println("Thread woke up!");
} catch (InterruptedException e) {
System.out.println("Thread was interrupted!");
}
}
}
使用wait()
wait()方法是Object类的一部分,它允许一个线程在某个对象上进行等待,直到另一个线程调用该对象的notify()或notifyAll()方法,使用wait()时需要注意以下几点:

- 对象锁:
wait()方法必须在一个同步方法或同步块中调用,并且该同步方法或同步块必须锁定对应的对象。 - 释放锁:调用
wait()方法后,当前线程会释放锁,其他线程可以进入该同步代码块。 - 异常处理:如果在等待期间发生中断,则
InterruptedException将被抛出。
public class WaitExample {
public synchronized void waitExample() {
try {
System.out.println("Thread is waiting...");
wait();
System.out.println("Thread woke up!");
} catch (InterruptedException e) {
System.out.println("Thread was interrupted!");
}
}
public static void main(String[] args) {
WaitExample example = new WaitExample();
new Thread(example::waitExample).start();
try {
Thread.sleep(1000);
example.notify(); // 唤醒等待的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
使用CountDownLatch
CountDownLatch是一个同步辅助类,用于协调多个线程的执行,它允许一个或多个线程等待其他线程完成操作,以下是其基本用法:
- 初始化:创建一个
CountDownLatch对象,并指定要等待的线程数。 - 等待:调用
await()方法,当前线程会等待,直到计数器降为0。 - 减少计数:可以通过调用
countDown()方法来减少计数器的值。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3); // 初始化计数器为3
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println("Thread " + Thread.currentThread().getName() + " is working...");
Thread.sleep(1000);
latch.countDown(); // 减少计数器
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
latch.await(); // 等待计数器降为0
System.out.println("All threads are done!");
}
}
使用CyclicBarrier
CyclicBarrier是一个同步辅助类,它允许一组线程在到达某个点时被阻塞,直到所有线程都到达该点后,这些线程才会继续执行,以下是其基本用法:
- 初始化:创建一个
CyclicBarrier对象,并指定需要等待的线程数。 - 等待:调用
await()方法,当前线程会等待,直到所有线程都到达。 - 重用:
CyclicBarrier可以在所有线程完成后重用,因为它不是线程安全的。
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("All threads have reached the barrier!");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
System.out.println("Thread " + Thread.currentThread().getName() + " is waiting at the barrier...");
barrier.await(); // 等待所有线程到达
System.out.println("Thread " + Thread.currentThread().getName() + " has passed the barrier!");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
使用Semaphore
Semaphore是一个用于控制对共享资源的访问的同步工具类,它可以用于实现信号量机制,允许一定数量的线程访问某个资源,以下是其基本用法:

- 初始化:创建一个
Semaphore对象,并指定可用的许可数。 - 获取许可:调用
acquire()方法获取许可。 - 释放许可:调用
release()方法释放许可。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 初始化信号量为2
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println("Thread " + Thread.currentThread().getName() + " is accessing the resource...");
Thread.sleep(1000);
semaphore.release(); // 释放许可
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
}
在Java中,有多种方法可以实现线程的等待执行,选择合适的方法取决于具体的应用场景和需求,理解每种方法的原理和用法对于编写高效、健壮的并发程序至关重要。