[英]Implementing producer consumer in Java
這是家庭作業的生產者消費者模式的實現。 下面的實現有什么問題。 我用谷歌搜索了各種實現,但我無法理解我的出了什么問題。
我有一個共享隊列
我在同一個鎖上同步生產者和消費者
執行
共享隊列:
class SharedQueue{
public static Queue<Integer> queue = new LinkedList<Integer>();
}
生產者線程:
//The producer thread
class Producer implements Runnable{
public void run()
{
synchronized (SharedQueue.queue)
{
if(SharedQueue.queue.size() >=5)
{
try {
SharedQueue.queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Random r = new Random();
int x = r.nextInt(10);
System.out.println("Inside Producer" + x);
SharedQueue.queue.offer(x);
SharedQueue.queue.notify();
}
}
}
消費者線程:
class Consumer implements Runnable{
public void run()
{
synchronized (SharedQueue.queue)
{
if(SharedQueue.queue.size() == 0)
{
try {
SharedQueue.queue.wait();
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
int k = SharedQueue.queue.remove();
System.out.println("Inside consumer" + k);
}
}
}
主程序
public class ProducerConsumerTest {
public static void main(String[] args)
{
Thread p = new Thread(new Producer());
Thread q = new Thread(new Consumer());
p.start();
q.start();
}
}
嘗試更換:
if(SharedQueue.queue.size() >= 5)
和:
while(SharedQueue.queue.size() >= 5)
還有這個:
if(SharedQueue.queue.size() == 0)
和:
while(SharedQueue.queue.size() == 0)
只是為了在調用notify()
后重新檢查條件。
我假設您希望這是生產者消費者的無限循環。 在 Eng.Fouad 更改之上,將兩個同步塊環繞在:
while (true)
並在消費者中添加一個通知
int k = SharedQueue.queue.remove();
// make the producer active again
SharedQueue.queue.notify();
System.out.println("Inside consumer " + k);
實現生產者消費者問題的簡單方法是使用信號量。
public class Semaphore {
int value;
public Semaphore(int intialValue) {
this.value = intialValue;
}
public synchronized void p() {
while (value <= 0) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
value = value - 1;
}
public synchronized void v() {
value = value + 1;
this.notify();
}
}
public class ProducerConsumerUsingSemaphore {
private static final int SIZE = 10;
public static void main(String[] args) {
Semaphore full = new Semaphore(0);
Semaphore empty = new Semaphore(SIZE);
Semaphore mutex = new Semaphore(1);
Vector<Integer> sQueue = new Vector<Integer>();
Thread producerThread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5000; i++) {
empty.p();
mutex.p();
System.out.println(Thread.currentThread().getName() + " is trying to insert item " + i);
sQueue.add(i);
mutex.v();
full.v();
}
}
});
Thread consumerThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
full.p();
mutex.p();
System.out.println(Thread.currentThread().getName() + " consuming item " + sQueue.remove(0));
mutex.v();
empty.v();
}
}
});
producerThread.setName("Producer");
consumerThread.setName("Consumer");
consumerThread.start();
producerThread.start();
}
}
您可以使用 ConcurrentLinkedQueue 來管理生產者和消費者的共享隊列。 可以利用ConcurrentHashMap>集合,它可以幫助Producer並發生產,Consumer也可以並發消費,將Producer生成的key保存在另一個collection對象中,ConcurrentHashMap>中Consumer可以找到自己的key並消費。
public class ProducerAndConsumer {
public static void main(String a[]) {
Resource resource = new Resource();
Producer producer = new Producer(resource);
Consumer consumer = new Consumer(resource);
producer.start();
consumer.start();
}
}
class Resource {
private int item = 0;
boolean flag = true;
public void getItem() {
while (true) {
synchronized (this) {
if (!flag) {
try {
System.out.println("Consumer consume item :" + item);
flag = true;
Thread.sleep(10);
notify();
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public void setItem() {
while (true) {
synchronized (this) {
if (flag) {
try {
item++;
System.out.println("Producer creating item :" + item);
flag = false;
Thread.sleep(10);
notify();
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
class Producer extends Thread {
Resource resource = null;
Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
resource.setItem();
}
}
class Consumer extends Thread {
Resource resource = null;
Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
resource.getItem();
}
}
只需將我的模式與毒丸一起使用:
public sealed interface BaseMessage {
final class ValidMessage<T> implements BaseMessage {
@Nonnull
private final T value;
public ValidMessage(@Nonnull T value) {
this.value = value;
}
@Nonnull
public T getValue() {
return value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ValidMessage<?> that = (ValidMessage<?>) o;
return value.equals(that.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
@Override
public String toString() {
return "ValidMessage{value=%s}".formatted(value);
}
}
final class PoisonedMessage implements BaseMessage {
public static final PoisonedMessage INSTANCE = new PoisonedMessage();
private PoisonedMessage() {
}
@Override
public String toString() {
return "PoisonedMessage{}";
}
}
}
public class Producer implements Callable<Void> {
@Nonnull
private final BlockingQueue<BaseMessage> messages;
Producer(@Nonnull BlockingQueue<BaseMessage> messages) {
this.messages = messages;
}
@Override
public Void call() throws Exception {
messages.put(new BaseMessage.ValidMessage<>(1));
messages.put(new BaseMessage.ValidMessage<>(2));
messages.put(new BaseMessage.ValidMessage<>(3));
messages.put(BaseMessage.PoisonedMessage.INSTANCE);
return null;
}
}
public class Consumer implements Callable<Void> {
@Nonnull
private final BlockingQueue<BaseMessage> messages;
private final int maxPoisons;
public Consumer(@Nonnull BlockingQueue<BaseMessage> messages, int maxPoisons) {
this.messages = messages;
this.maxPoisons = maxPoisons;
}
@Override
public Void call() throws Exception {
int poisonsReceived = 0;
while (poisonsReceived < maxPoisons && !Thread.currentThread().isInterrupted()) {
BaseMessage message = messages.take();
if (message instanceof BaseMessage.ValidMessage<?> vm) {
Integer value = (Integer) vm.getValue();
System.out.println(value);
} else if (message instanceof BaseMessage.PoisonedMessage) {
++poisonsReceived;
} else {
throw new IllegalArgumentException("Invalid BaseMessage type: " + message);
}
}
return null;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.