用Java多线程实现2.三个进程P1、P2、P3使用包含N个单元的缓冲区,P1每次用Produce()生成一个正整数并用put()送入缓冲区的某个空单元;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从缓冲区中取出偶数并用counteven()统计偶数个数,请用信号量实现三个进程的同步与互斥活动。
时间: 2024-03-14 14:47:17 浏览: 82
以下是一个可能的Java多线程实现方案:
```java
import java.util.concurrent.Semaphore;
public class ProducerConsumer {
private static final int N = 10; // 缓冲区大小
private static Semaphore mutex = new Semaphore(1); // 用于互斥操作缓冲区
private static Semaphore empty = new Semaphore(N); // 用于追踪缓冲区空位数量
private static Semaphore full = new Semaphore(0); // 用于追踪缓冲区已有元素数量
private static Semaphore countOdd = new Semaphore(1); // 用于互斥操作奇数计数器
private static Semaphore countEven = new Semaphore(1); // 用于互斥操作偶数计数器
private static Integer[] buffer = new Integer[N]; // 缓冲区
private static int oddCount = 0; // 奇数计数器
private static int evenCount = 0; // 偶数计数器
public static void main(String[] args) {
Thread producerThread = new Thread(new Producer());
Thread consumerOddThread = new Thread(new ConsumerOdd());
Thread consumerEvenThread = new Thread(new ConsumerEven());
producerThread.start();
consumerOddThread.start();
consumerEvenThread.start();
}
static class Producer implements Runnable {
@Override
public void run() {
while (true) {
Integer item = Produce(); // 生产一个元素
try {
empty.acquire(); // 等待缓冲区有空位
mutex.acquire(); // 互斥操作缓冲区
int index = getNextAvailableIndex(); // 找到下一个空位
buffer[index] = item; // 放入元素
mutex.release(); // 释放缓冲区
full.release(); // 增加缓冲区中元素数量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class ConsumerOdd implements Runnable {
@Override
public void run() {
while (true) {
try {
full.acquire(); // 等待缓冲区有元素
mutex.acquire(); // 互斥操作缓冲区
int index = getNextAvailableIndex(true); // 找到下一个奇数
int item = buffer[index];
buffer[index] = null;
mutex.release(); // 释放缓冲区
empty.release(); // 增加缓冲区空位数量
countOdd.acquire(); // 互斥操作奇数计数器
oddCount++;
countOdd.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class ConsumerEven implements Runnable {
@Override
public void run() {
while (true) {
try {
full.acquire(); // 等待缓冲区有元素
mutex.acquire(); // 互斥操作缓冲区
int index = getNextAvailableIndex(false); // 找到下一个偶数
int item = buffer[index];
buffer[index] = null;
mutex.release(); // 释放缓冲区
empty.release(); // 增加缓冲区空位数量
countEven.acquire(); // 互斥操作偶数计数器
evenCount++;
countEven.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取下一个可用的缓冲区索引
* @return 下一个可用的缓冲区索引
*/
private static int getNextAvailableIndex() {
return getNextAvailableIndex(false);
}
/**
* 获取下一个可用的缓冲区索引
* @param isOdd 是否为奇数
* @return 下一个可用的缓冲区索引
*/
private static int getNextAvailableIndex(boolean isOdd) {
for (int i = 0; i < buffer.length; i++) {
Integer item = buffer[i];
if (item != null && item % 2 == (isOdd ? 1 : 0)) {
return i;
}
}
return -1;
}
/**
* 生成一个正整数
* @return 生成的正整数
*/
private static Integer Produce() {
return (int) (Math.random() * 100) + 1;
}
}
```
在以上代码中,我们使用了三个线程来模拟生产者和两个消费者。生产者不断生产元素,并将它们放入缓冲区中。两个消费者不断从缓冲区中取出元素,如果该元素是奇数,则奇数计数器加一;如果该元素是偶数,则偶数计数器加一。使用信号量可以保证缓冲区的同步和互斥操作,同时也能保证计数器的同步和互斥操作。
阅读全文