From fcbf8e318f9fed3b5ed557d3d0c380da75d09aa1 Mon Sep 17 00:00:00 2001 From: Juan Lauer Garrido <juan.lauer_garrido@student.reutlingen-university.de> Date: Mon, 13 Jun 2022 23:32:39 +0200 Subject: [PATCH] Push new status --- ErzeugerVerbraucher/.idea/vcs.xml | 6 ++ .../out/production/Aufgabe4/Main.class | Bin 516 -> 0 bytes ErzeugerVerbraucher/src/Buffer.java | 84 ++++++++++-------- ErzeugerVerbraucher/src/Car.java | 1 - ErzeugerVerbraucher/src/Consumer.java | 63 ++++++++----- ErzeugerVerbraucher/src/Main.java | 35 ++++++-- ErzeugerVerbraucher/src/Producer.java | 49 +++++++++- 7 files changed, 170 insertions(+), 68 deletions(-) create mode 100644 ErzeugerVerbraucher/.idea/vcs.xml delete mode 100644 ErzeugerVerbraucher/out/production/Aufgabe4/Main.class diff --git a/ErzeugerVerbraucher/.idea/vcs.xml b/ErzeugerVerbraucher/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/ErzeugerVerbraucher/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$/.." vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/ErzeugerVerbraucher/out/production/Aufgabe4/Main.class b/ErzeugerVerbraucher/out/production/Aufgabe4/Main.class deleted file mode 100644 index e92adf7d8f256d86b5d8e1080fd1e655c523f9d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmZvZ%TB^T6o&tSLTRmnAb3~m3S8Kw3k(|*<Dy;?3>#MiOmN7wV@lEZSh~=}g%99E z8P60GHDQuDlk=bRe{=i%dj9~>#es_)@-{3F1r!-76aK&h#p7{sHJFHD%1}I!u}r%R z`BuB{pajQ;>tPArzxLkKG!+qb=^2^oVFr>qxK3o8_R>V~s8hlUgLf{J(#=PmsFClY zf>j$;4>hbY)E2lH?0dsdF=1PCZgxO|%6Qyq_iZ#7tP3uw!#dR?!B7rmEG}o!KqNPO zph&5PddO9uC(`6UqLtpsDP1u%<_@`|4AN-bF4~9cJQ-7eZ9$pA?de%E6lc<G=NRIV zxek2P>5<LIfthEfxK3F>E2Fh=_y+czl{YAwGH7m6^yUrN!Zu|NcCbr|F&}3z(q3R! cmtRr-1(+`d^7K>IABclJ?32#Wq?m*M4VH#yH~;_u diff --git a/ErzeugerVerbraucher/src/Buffer.java b/ErzeugerVerbraucher/src/Buffer.java index e91ea1b..a1101dc 100644 --- a/ErzeugerVerbraucher/src/Buffer.java +++ b/ErzeugerVerbraucher/src/Buffer.java @@ -1,53 +1,65 @@ -import java.util.ArrayList; -import java.util.concurrent.Semaphore; -import java.lang.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +/** + * A generic and atomically safe Buffer data structure for holding values important in multithreaded use cases. + * @param <T> The type of item to hold within the Buffer + */ public class Buffer<T> { + AtomicReferenceArray<T> items; + AtomicInteger itemCount; int size; - public Semaphore sem; - public ArrayList<T> items = new ArrayList<T>(size); - public Buffer(int size){ - assert size >= 0; + /** + * Constructor for Buffer data structure + * @param size The size of the Buffer + */ + public Buffer(int size) { + this.items = new AtomicReferenceArray<>(size); + this.itemCount = new AtomicInteger(0); this.size = size; - } - public void push(T e) throws InterruptedException { - assert(e!=null); - assert(!full()); - if(this.full()) { - System.out.println("Buffer is full"); + /** + * Push an item to the Buffer + * @param item The item to be pushed + * @throws IllegalStateException Thrown if pushing would exceed the maximum allowed size + */ + public void push(T item) throws IllegalStateException { + if (this.itemCount.get() >= this.size) { + throw new IllegalStateException(); } - this.sem.acquire(); - items.add(e); - this.sem.release(); + this.items.set(this.itemCount.get(), item); + this.itemCount.incrementAndGet(); } -// public ArrayList<T> pop() throws InterruptedException{ -// sem.acquire(); -// item = items.remove(0); -// sem.release(); -// return item; -// -// } - - public boolean full() throws InterruptedException { - sem.acquire(); - boolean is_full = items.size()==size; - sem.release(); - - return is_full; + /** + * Pop an item from the Buffer + * @return The item to be popped + * @throws IllegalStateException Thrown if popping would underflow the minimum allowed size + */ + public T pop() throws IllegalStateException { + if (this.itemCount.get() <= 0) { /// ORIGINAL <1 + throw new IllegalStateException(); + } + return this.items.getAndSet(this.itemCount.getAndDecrement(), null); } - public boolean empty() throws InterruptedException { - sem.acquire(); - boolean is_empty = items.size()==0; - sem.release(); - - return is_empty; + /** + * Check whether the Buffer is full + * @return True if the Buffer is full, False otherwise + */ + public boolean full() { + return this.itemCount.get() >= this.size; + } + /** + * Check whether the Buffer is empty + * @return True if the Buffer is empty, False otherwise + */ + public boolean empty() { + return Integer.valueOf(this.itemCount.get()).equals(0); } } diff --git a/ErzeugerVerbraucher/src/Car.java b/ErzeugerVerbraucher/src/Car.java index fa9b889..5cad0e4 100644 --- a/ErzeugerVerbraucher/src/Car.java +++ b/ErzeugerVerbraucher/src/Car.java @@ -1,3 +1,2 @@ public class Car { - } diff --git a/ErzeugerVerbraucher/src/Consumer.java b/ErzeugerVerbraucher/src/Consumer.java index 2b16e6a..e576eb8 100644 --- a/ErzeugerVerbraucher/src/Consumer.java +++ b/ErzeugerVerbraucher/src/Consumer.java @@ -1,34 +1,49 @@ -import com.sun.jdi.event.ThreadDeathEvent; -import com.sun.jdi.event.ThreadStartEvent; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; -import java.util.Random; -import java.lang.*; +public class Consumer implements Runnable { + private final Buffer<Car> buffer; + private final int interval; + private final AtomicBoolean asleep; + private final AtomicBoolean wakeCall; -public class Consumer{ - int interval; - ThreadDeathEvent consumerThread; - ThreadStartEvent producerThread; - Buffer buffer; - public Consumer(Buffer buffer, int interval, ThreadDeathEvent consumerThread, ThreadStartEvent producerThread) { - assert buffer != null; - assert interval > 0; + public Consumer(Buffer<Car> buffer, int interval, AtomicBoolean asleep, AtomicBoolean wakeCall) { this.buffer = buffer; this.interval = interval; - this.consumerThread = consumerThread; - this.producerThread = producerThread; - this.run(); - - assert this.interval == interval; + this.asleep = asleep; + this.wakeCall = wakeCall; } - public void run() throws InterruptedException{ - assert this.interval > 0; - while(this.interval > 0) { - Thread.sleep(new Random().nextInt(interval)); + @Override + public void run() { + while(true) { + try { + TimeUnit.SECONDS.sleep((int)(Math.random() * this.interval + 1)); + + boolean wasFull = this.buffer.full(); + + if (!this.asleep.get()) { + System.out.printf("%s consumer ...%n", Thread.currentThread().getId()); + + if (!this.buffer.empty()) { + this.buffer.pop(); + System.out.printf( + "%s consumer TAKING OUT %s/%s %n", + Thread.currentThread().getId(), + this.buffer.itemCount, + this.buffer.size + ); + } else { + this.asleep.set(true); + } + } - boolean was_full = this.buffer.full(); - assert was_full instanceof - if(!this.consumerThread.) + if (wasFull) { + this.wakeCall.set(false); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } } } diff --git a/ErzeugerVerbraucher/src/Main.java b/ErzeugerVerbraucher/src/Main.java index df9fa5f..c842161 100644 --- a/ErzeugerVerbraucher/src/Main.java +++ b/ErzeugerVerbraucher/src/Main.java @@ -1,12 +1,35 @@ +import java.util.concurrent.atomic.AtomicBoolean; + public class Main { public static void main(String[] args) { - Buffer b1 = new Buffer(5); - try { - b1.push(5); - } catch (InterruptedException e) { - System.out.println(e); + Buffer<Car> buffer = new Buffer<>(5); + AtomicBoolean consumerStatus = new AtomicBoolean(false); + AtomicBoolean producerStatus = new AtomicBoolean(false); + int consumerCount = Integer.parseInt(args[0]); + int producerCount = Integer.parseInt(args[1]); + + for (int i = 0; i < consumerCount; i++) { + Thread consumerThread = new Thread(new Runnable() { + @Override + public void run() { + Consumer consumer = new Consumer(buffer, 15, consumerStatus, producerStatus); + consumer.run(); + } + }); + + consumerThread.start(); } + for (int i = 0; i < producerCount; i++) { + Thread producerThread = new Thread(new Runnable() { + @Override + public void run() { + Producer producer = new Producer(buffer, 15, producerStatus, consumerStatus); + producer.run(); + } + }); + producerThread.start(); + } } -} +} \ No newline at end of file diff --git a/ErzeugerVerbraucher/src/Producer.java b/ErzeugerVerbraucher/src/Producer.java index e715fa6..2f89cf4 100644 --- a/ErzeugerVerbraucher/src/Producer.java +++ b/ErzeugerVerbraucher/src/Producer.java @@ -1,2 +1,49 @@ -public class Producer { +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +public class Producer implements Runnable { + private final Buffer<Car> buffer; + private final int interval; + private final AtomicBoolean asleep; + private final AtomicBoolean wakeCall; + + public Producer(Buffer<Car> buffer, int interval, AtomicBoolean asleep, AtomicBoolean wakeCall) { + this.buffer = buffer; + this.interval = interval; + this.asleep = asleep; + this.wakeCall = wakeCall; + } + + @Override + public void run() { + while(true) { + try { + TimeUnit.SECONDS.sleep((int)(Math.random() * this.interval + 1)); + + boolean wasEmpty = this.buffer.empty(); + + if (!this.asleep.get()) { + System.out.printf("%s producer ...%n", Thread.currentThread().getId()); + + if (!this.buffer.full()) { + this.buffer.push(new Car()); + System.out.printf( + "%s producer PUSHING IN %s/%s %n", + Thread.currentThread().getId(), + this.buffer.itemCount, + this.buffer.size + ); + } else { + this.asleep.set(true); + } + } + + if (wasEmpty) { + this.wakeCall.set(false); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } } -- GitLab