用java编写程序:有两个线程,线程A负责对一个数据进行加法操作,线程B负责对这个数据进行减法操作。初始时数据为0。要求操作过程中始终保证数据的有效性,即在任意时刻都不能小于0。如果数据小于0,线程必须等待,直到数据变得可用。
时间: 2024-02-01 15:13:31 浏览: 72
以下是一个可能的解决方案:
```java
public class AdditionSubtraction {
private static int data = 0;
private static Object lock = new Object();
public static void main(String[] args) {
Thread threadA = new Thread(new AdditionTask());
Thread threadB = new Thread(new SubtractionTask());
threadA.start();
threadB.start();
}
private static class AdditionTask implements Runnable {
@Override
public void run() {
while (true) {
synchronized (lock) {
while (data < 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data++;
System.out.println("Thread A: data = " + data);
lock.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class SubtractionTask implements Runnable {
@Override
public void run() {
while (true) {
synchronized (lock) {
while (data < 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
data--;
System.out.println("Thread B: data = " + data);
lock.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
```
在这个程序中,我们使用了一个静态变量 `data` 来表示数据,以及一个静态对象 `lock` 作为锁。线程 A 和线程 B 分别实现了 `Runnable` 接口,并在 `run()` 方法中编写了具体的逻辑。
在每个线程的 `run()` 方法中,我们首先进入了一个 `synchronized` 块,以确保线程安全。然后,我们使用一个 `while` 循环来等待数据变得可用。如果当前数据小于 0,线程就会进入等待状态,并释放锁。当数据变得可用时,线程就会重新争抢锁。这里使用 `while` 循环而不是 `if` 条件判断是为了避免虚假唤醒。
如果当前数据可用,线程就会进行加法或减法操作,并输出当前数据。最后,我们使用 `notifyAll()` 方法来唤醒所有等待的线程,以确保它们能够及时获取到新的数据并进行操作。
在 `main()` 方法中,我们创建了线程 A 和线程 B,并启动它们。由于两个线程都是无限循环的,因此程序会一直运行下去,直到手动终止。
阅读全文