Java中的线程同步与阻塞
在多线程编程中,线程的同步和阻塞是非常重要的概念。同步能够帮助我们避免多个线程在访问共享资源时出现竞争条件,而阻塞和唤醒则允许我们灵活地管理线程的执行。本文将带领大家了解如何在Java中实现同步阻塞并唤醒指定线程。
整体流程
我们可以将整个过程分为几个步骤。以下是一个关于实现步骤的表格,清晰地列出了每一步的内容。
步骤 | 描述 |
---|---|
1 | 创建一个共享资源 |
2 | 创建工作线程 |
3 | 使用 wait() 阻塞线程 |
4 | 使用 notify() 或 notifyAll() 唤醒阻塞线程 |
5 | 测试代码并观察各线程的行为 |
接下来,我们将详细讲解每一个步骤,提供具体的代码示例和注释。
步骤1:创建一个共享资源
我们需要一个共享资源。通常这是一个简单的对象,例如一把锁或条件变量。下面是一个简单的共享资源类:
public class SharedResource {
private int number = 0;
public synchronized void increment() {
number++;
System.out.println("Incremented: " + number);
notify(); // 唤醒等待的线程
}
public synchronized int getNumber() {
return number;
}
public synchronized void waitForNumber(int target) throws InterruptedException {
while (number < target) {
wait(); // 阻塞当前线程
}
System.out.println("Reached target: " + target);
}
}
代码解释
increment()
: 增加共享变量number
的值,并在完成后唤醒任何正在等待的线程。getNumber()
: 返回当前的number
值。waitForNumber(int target)
: 当number
小于目标值时,调用wait()
方法阻塞当前线程。
步骤2:创建工作线程
现在我们需要创建两个线程,一个负责增量操作,另一个负责等待操作。
public class WorkerThread extends Thread {
private SharedResource resource;
public WorkerThread(SharedResource resource) {
this.resource = resource;
}
@Override
public void run() {
try {
if (this.getName().equals("Incrementor")) {
for (int i = 0; i < 5; i++) {
resource.increment(); // 调用共享资源的increment方法
Thread.sleep(500); // 模拟一些工作
}
} else {
resource.waitForNumber(3); // 等待number达到3
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代码解释
WorkerThread
类扩展了Thread
,并在构造函数中传入共享资源。run()
方法中执行分支逻辑,一个线程调用increment()
,另一个线程调用waitForNumber()
。
步骤3:使用 wait()
阻塞线程
在前面 waitForNumber(int target)
方法中,我们已经实现了使用 wait()
阻塞线程的逻辑。线程会在 number
的值未达到目标值时进入阻塞状态。
步骤4:使用 notify()
唤醒线程
我们在 increment()
方法里调用了 notify()
,这是唤醒等待线程的关键。它会唤醒一个正在等待监视器的线程。
步骤5:测试代码并观察各线程的行为
接下来,我们创建一个主类来测试我们的工作线程。
public class Main {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
Thread incrementor = new WorkerThread(resource);
incrementor.setName("Incrementor");
Thread waiter = new WorkerThread(resource);
waiter.setName("Waiter");
waiter.start(); // 先启动等待线程
incrementor.start(); // 再启动增量线程
}
}
代码解释
- 在
Main
类中,我们创建了SharedResource
的实例。 - 创建了两条线程:一个是用来增加数字的(
Incrementor
),另一个是等待数字达到特定目标的(Waiter
)。 - 首先启动
waiter
线程,然后启动incrementor
线程。
整体运行流程
- 等待线程首先开始,调用
waitForNumber(3)
方法。如果number
小于3,它会进入阻塞状态。 - 随后增量线程开始执行,逐步增加
number
的值,同时调用notify()
唤醒所有等待的线程。 - 当
number
的值达到3时,等待线程被唤醒,继续执行,输出结果。
结尾
通过以上步骤,我们成功实现了线程的同步、阻塞和唤醒机制。本篇文章展示了如何使用 Java 提供的 wait()
和 notify()
方法来管理线程之间的协调与通信。理解这些概念后,您在并发编程中的能力将会大大增强。如果你在今后的项目中需要实现复杂的线程管理,这些基本操作会成为你不可或缺的工具。
希望这篇文章对刚入行的你有所帮助,祝你在Java开发的旅程中获得更多乐趣和成就!如果您还有疑问,不妨在社区里问问,有很多乐意分享经验的人。祝编程愉快!