Java编程生产者消费者实现的四种方法
生产者消费者问题是指在生产者和消费者之间同步的问题。生产者一直在生产消息,消费者一直在从队列中取走消息,并且队列中只能存储有限的消息。Java中提供了多种实现生产者消费者问题的方法,具体如下:
方法一:使用wait()和notify()方法
这是最基本的一种实现方式。使用wait()方法让生产者线程等待,当消息队列满时,调用notify()方法,让消费者线程去消费消息。反之,当队列为空时,调用wait()方法,让生产者线程去产生消息。下面是一个简单的示例:
class MessageQueue {
private int[] queue = new int[10];
private int front = 0, rear = 0, size = 0;
public synchronized void write(int num) throws InterruptedException {
while (size == queue.length) {
wait();
}
queue[rear] = num;
rear = (rear + 1) % queue.length;
size++;
notifyAll();
}
public synchronized int read() throws InterruptedException {
while (size == 0) {
wait();
}
int num = queue[front];
front = (front + 1) % queue.length;
size--;
notifyAll();
return num;
}
}
class Producer extends Thread {
private MessageQueue queue;
public Producer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println("put " + i + " into queue.");
queue.write(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
private MessageQueue queue;
public Consumer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int num = queue.read();
System.out.println("get " + num + " from queue.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class WaitNotifyDemo {
public static void main(String[] args) throws InterruptedException {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
方法二:使用Lock和Condition
使用Lock和Condition可以实现更为灵活和安全的线程同步。Condition的await()方法和signal()方法就相当于wait()和notify()方法,但是Condition比wait、notify更加安全可靠。示例代码如下:
class MessageQueue {
private int[] queue = new int[10];
private int front = 0, rear = 0, size = 0;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public void write(int num) throws InterruptedException {
lock.lock();
try {
while (size == queue.length) {
notFull.await();
}
queue[rear] = num;
rear = (rear + 1) % queue.length;
size++;
notEmpty.signalAll();
} finally {
lock.unlock();
}
}
public int read() throws InterruptedException {
lock.lock();
try {
while (size == 0) {
notEmpty.await();
}
int num = queue[front];
front = (front + 1) % queue.length;
size--;
notFull.signalAll();
return num;
} finally {
lock.unlock();
}
}
}
class Producer extends Thread {
private MessageQueue queue;
public Producer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println("put " + i + " into queue.");
queue.write(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
private MessageQueue queue;
public Consumer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int num = queue.read();
System.out.println("get " + num + " from queue.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class LockConditionDemo {
public static void main(String[] args) throws InterruptedException {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
方法三:使用BlockingQueue
Java中提供了BlockingQueue接口可以很方便的实现生产者消费者队列。BlockingQueue常用的实现类有ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。示例代码如下:
class Producer extends Thread {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println("put " + i + " into queue.");
queue.put(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int num = queue.take();
System.out.println("get " + num + " from queue.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
方法四:使用Semaphore
使用Semaphore也可以实现生产者消费者问题,但是需要通过计数器来控制生产者和消费者的线程数。当计数器为0时,消费者线程需要等待;当计数器达到阈值时,生产者线程需要等待。具体示例代码如下:
class MessageQueue {
private int[] queue = new int[10];
private int front = 0, rear = 0, size = 0;
private Semaphore notFull = new Semaphore(10);
private Semaphore notEmpty = new Semaphore(0);
public void write(int num) throws InterruptedException {
notFull.acquire();
queue[rear] = num;
rear = (rear + 1) % queue.length;
size++;
notEmpty.release();
}
public int read() throws InterruptedException {
notEmpty.acquire();
int num = queue[front];
front = (front + 1) % queue.length;
size--;
notFull.release();
return num;
}
}
class Producer extends Thread {
private MessageQueue queue;
public Producer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
System.out.println("put " + i + " into queue.");
queue.write(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
private MessageQueue queue;
public Consumer(MessageQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int num = queue.read();
System.out.println("get " + num + " from queue.");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class SemaphoreDemo {
public static void main(String[] args) throws InterruptedException {
MessageQueue queue = new MessageQueue();
Producer producer = new Producer(queue);
Consumer consumer = new Consumer(queue);
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
以上是Java编程生产者消费者实现的四种方法的详细攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java编程生产者消费者实现的四种方法 - Python技术站