Laboraufgaben für Kap. 3
parent
cdcb0c69fc
commit
dff9d7719f
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Sensor extends Thread {
|
||||
|
||||
// eigentlich abstract
|
||||
|
||||
private final long frequency;
|
||||
|
|
|
@ -3,6 +3,7 @@ package pp;
|
|||
import java.util.Random;
|
||||
|
||||
public class Thermometer extends Sensor {
|
||||
|
||||
private final Random rand;
|
||||
|
||||
public Thermometer(long frequency) {
|
||||
|
@ -12,8 +13,7 @@ public class Thermometer extends Sensor {
|
|||
|
||||
@Override
|
||||
protected String reading() {
|
||||
return String.format("(%04d freq.): %3d°C", getFrequency(),
|
||||
this.rand.nextInt(100));
|
||||
return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100));
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Sensor extends Thread {
|
||||
|
||||
// eigentlich abstract
|
||||
|
||||
private final long frequency;
|
||||
|
|
|
@ -3,6 +3,7 @@ package pp;
|
|||
import java.util.Random;
|
||||
|
||||
public class Thermometer extends Sensor {
|
||||
|
||||
private final Random rand;
|
||||
|
||||
public Thermometer(long frequency) {
|
||||
|
@ -12,8 +13,7 @@ public class Thermometer extends Sensor {
|
|||
|
||||
@Override
|
||||
protected String reading() {
|
||||
return String.format("(%04d freq.): %3d°C", getFrequency(),
|
||||
this.rand.nextInt(100));
|
||||
return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100));
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package pp;
|
||||
|
||||
class MyWorker implements Runnable {
|
||||
|
||||
private Thread self;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(
|
||||
this.self.getName() + ": ID => " + this.self.threadId());
|
||||
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package pp;
|
||||
|
||||
class MyWorkerCoop implements Runnable {
|
||||
|
||||
private Thread self;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(
|
||||
this.self.getName() + ": ID => " + this.self.threadId());
|
||||
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Starter {
|
||||
|
||||
static int WORKERS = 200;
|
||||
|
||||
public static void main(String... args) {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package pp;
|
||||
|
||||
class MyWorker implements Runnable {
|
||||
|
||||
private Thread self;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(
|
||||
this.self.getName() + ": ID => " + this.self.threadId());
|
||||
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package pp;
|
||||
|
||||
class MyWorkerCoop implements Runnable {
|
||||
|
||||
private Thread self;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(
|
||||
this.self.getName() + ": ID => " + this.self.threadId());
|
||||
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package pp;
|
||||
|
||||
public class Starter {
|
||||
|
||||
static int WORKERS = 200;
|
||||
|
||||
public static void main(String... args) {
|
||||
for (var i = 0; i < Starter.WORKERS; i++) {
|
||||
var t = new Thread(new MyWorkerCoop(),
|
||||
String.format("Worker-%03d", i));
|
||||
var t = new Thread(new MyWorkerCoop(), String.format("Worker-%03d", i));
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
package pp;
|
||||
|
||||
public class StarterInner {
|
||||
|
||||
static int WORKERS = 200;
|
||||
|
||||
public static void main(String... args) {
|
||||
for (var i = 0; i < StarterInner.WORKERS; i++) {
|
||||
var t = new Thread(new Runnable() {
|
||||
var t = new Thread(
|
||||
new Runnable() {
|
||||
private Thread self;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(this.self.getName() + ": ID => "
|
||||
+ this.self.threadId());
|
||||
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||
}
|
||||
}
|
||||
}, String.format("Worker-%03d", i));
|
||||
},
|
||||
String.format("Worker-%03d", i)
|
||||
);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
package pp;
|
||||
|
||||
public class StarterLambda {
|
||||
|
||||
static int WORKERS = 200;
|
||||
|
||||
public static void main(String... args) {
|
||||
for (var i = 0; i < StarterLambda.WORKERS; i++) {
|
||||
var t = new Thread(() -> {
|
||||
var t = new Thread(
|
||||
() -> {
|
||||
var self = Thread.currentThread();
|
||||
while (true) {
|
||||
System.out.println(
|
||||
self.getName() + ": ID => " + self.threadId());
|
||||
System.out.println(self.getName() + ": ID => " + self.threadId());
|
||||
}
|
||||
}, String.format("Worker-%03d", i));
|
||||
},
|
||||
String.format("Worker-%03d", i)
|
||||
);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Runner {
|
||||
|
||||
public static void main(String... args) {
|
||||
var task = new Task();
|
||||
var thread = new Thread(task);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Task implements Runnable {
|
||||
|
||||
private volatile Thread self;
|
||||
private volatile boolean stopped = false;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Runner {
|
||||
|
||||
public static void main(String... args) {
|
||||
var task = new Task();
|
||||
var thread = new Thread(task);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pp;
|
||||
|
||||
public class Task implements Runnable {
|
||||
|
||||
private volatile Thread self;
|
||||
private volatile boolean stopped = false;
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ public class MemoryBarrierTest extends Thread {
|
|||
t.start();
|
||||
Thread.sleep(1000);
|
||||
t.stopped = true;
|
||||
System.out.println(
|
||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ public class MemoryBarrierTest1 extends Thread {
|
|||
t.start();
|
||||
Thread.sleep(1000);
|
||||
t.stopped = true;
|
||||
System.out.println(
|
||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ public class MemoryBarrierTest1b extends Thread {
|
|||
t.start();
|
||||
Thread.sleep(1000);
|
||||
t.setStopped(true);
|
||||
System.out.println(
|
||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ public class MemoryBarrierTest2 extends Thread {
|
|||
t.start();
|
||||
Thread.sleep(1000);
|
||||
t.stopped = true;
|
||||
System.out.println(
|
||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ public class MemoryBarrierTest5 extends Thread {
|
|||
Thread.currentThread().interrupt();
|
||||
}
|
||||
this.stopped = true;
|
||||
System.out.println(
|
||||
"Stopper thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Stopper thread set stopped on MemoryBarrierTest-Thread.");
|
||||
});
|
||||
this.stopper.start();
|
||||
}
|
||||
|
@ -40,7 +39,5 @@ public class MemoryBarrierTest5 extends Thread {
|
|||
public static void main(String... args) throws InterruptedException {
|
||||
var t = new MemoryBarrierTest5();
|
||||
t.start();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ public class MemoryBarrierTest6 extends Thread {
|
|||
t.start();
|
||||
Thread.sleep(1000);
|
||||
t.stopped = true;
|
||||
System.out.println(
|
||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package pp;
|
|||
import java.util.Random;
|
||||
|
||||
public class MyThreadLocalRandom0 implements Runnable {
|
||||
|
||||
public static long now = System.currentTimeMillis();
|
||||
public Random rand = new Random(now);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package pp;
|
|||
import java.util.Random;
|
||||
|
||||
public class MyThreadLocalRandom1 implements Runnable {
|
||||
|
||||
public static long now = System.currentTimeMillis();
|
||||
public ThreadLocal<Random> rand = new ThreadLocal<>() {
|
||||
@Override
|
||||
|
|
|
@ -3,6 +3,7 @@ package pp;
|
|||
import java.util.Random;
|
||||
|
||||
public class MyThreadLocalRandom2 implements Runnable {
|
||||
|
||||
public static long now = System.currentTimeMillis();
|
||||
public static ThreadLocal<Random> rand = new ThreadLocal<>() {
|
||||
@Override
|
||||
|
|
|
@ -21,9 +21,7 @@ public class Factory {
|
|||
() -> {
|
||||
Type object = Factory.getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -20,9 +20,7 @@ public class Factory0 {
|
|||
() -> {
|
||||
var object = getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -20,9 +20,7 @@ public class Factory1 {
|
|||
() -> {
|
||||
var object = getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -22,9 +22,7 @@ public class Factory2 {
|
|||
() -> {
|
||||
var object = getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -23,9 +23,7 @@ public class Factory3 {
|
|||
() -> {
|
||||
var object = Factory3.getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -24,9 +24,7 @@ public class Factory4 {
|
|||
() -> {
|
||||
var object = getInstance();
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() +
|
||||
": serial of instance = " +
|
||||
object.getSerial()
|
||||
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||
);
|
||||
},
|
||||
String.format("InstanceGrabber-%02d", i)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "Dinnierende Philosoph:innen"
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-01-SynchPhilosopher.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-dinierende-philosophinnen)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.01-SynchPhilosopher</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.PhilosopherExperiment</exec.mainClass>
|
||||
<maven.compiler.release>19</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,3 @@
|
|||
package pp;
|
||||
|
||||
public class Chopstick {}
|
|
@ -0,0 +1,77 @@
|
|||
package pp;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Philosopher extends Thread {
|
||||
|
||||
static final int MAX_THINKING_DURATION_MS = 1000;
|
||||
static final int MAX_EATING_DURATION_MS = 3000;
|
||||
static final int MAX_TAKING_TIME_MS = 1000;
|
||||
|
||||
private final Chopstick left;
|
||||
private final Chopstick right;
|
||||
private final Random random;
|
||||
private int eaten;
|
||||
private final int seat;
|
||||
|
||||
private volatile boolean stop;
|
||||
|
||||
private void log(String message) {
|
||||
synchronized (Philosopher.class) {
|
||||
for (var i = 1; i <= this.seat; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
System.out.println(threadId() + " " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPhilosopher() {
|
||||
log("stopping");
|
||||
this.stop = true;
|
||||
interrupt();
|
||||
}
|
||||
|
||||
public Philosopher(int seat, Chopstick left, Chopstick right) {
|
||||
this.stop = false;
|
||||
this.seat = seat;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.random = new Random();
|
||||
this.eaten = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log("starting");
|
||||
try {
|
||||
while (!this.stop) {
|
||||
think();
|
||||
eat();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
log("stopped; eaten=" + this.eaten);
|
||||
}
|
||||
|
||||
private void think() throws InterruptedException {
|
||||
Thread.sleep(this.random.nextInt(MAX_THINKING_DURATION_MS));
|
||||
}
|
||||
|
||||
private void eat() throws InterruptedException {
|
||||
log("try taking left");
|
||||
synchronized (this.left) {
|
||||
log("left acquired");
|
||||
Thread.sleep(this.random.nextInt(MAX_TAKING_TIME_MS));
|
||||
log("try taking right");
|
||||
synchronized (this.right) {
|
||||
log("right acquired");
|
||||
log("eating");
|
||||
this.eaten++;
|
||||
Thread.sleep(this.random.nextInt(MAX_EATING_DURATION_MS));
|
||||
}
|
||||
log("right released");
|
||||
}
|
||||
log("left released");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package pp;
|
||||
|
||||
public class PhilosopherExperiment {
|
||||
|
||||
static final int PHILOSOPHER_NUM = 5;
|
||||
static final int EXP_DURATION_MS = 20000;
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var chopsticks = new Chopstick[PHILOSOPHER_NUM];
|
||||
var philosophers = new Philosopher[PHILOSOPHER_NUM];
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
chopsticks[i] = new Chopstick();
|
||||
}
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
philosophers[i] = new Philosopher(i, chopsticks[i], chopsticks[(i + 1) % PHILOSOPHER_NUM]);
|
||||
}
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
philosophers[i].start();
|
||||
}
|
||||
Thread.sleep(EXP_DURATION_MS);
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
philosophers[i].stopPhilosopher();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "Dinnierende Philosoph:innen"
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-01-SynchPhilosopher.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-dinierende-philosophinnen)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.01-SynchPhilosopher_solution</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.PhilosopherExperiment</exec.mainClass>
|
||||
<maven.compiler.release>19</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,3 @@
|
|||
package pp;
|
||||
|
||||
public class Chopstick {}
|
|
@ -0,0 +1,77 @@
|
|||
package pp;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class Philosopher extends Thread {
|
||||
|
||||
static final int MAX_THINKING_DURATION_MS = 1000;
|
||||
static final int MAX_EATING_DURATION_MS = 3000;
|
||||
static final int MAX_TAKING_TIME_MS = 1000;
|
||||
|
||||
private final Chopstick left;
|
||||
private final Chopstick right;
|
||||
private final Random random;
|
||||
private int eaten;
|
||||
private final int seat;
|
||||
|
||||
private volatile boolean stop;
|
||||
|
||||
private void log(String message) {
|
||||
synchronized (Philosopher.class) {
|
||||
for (var i = 1; i <= this.seat; i++) {
|
||||
System.out.print(" ");
|
||||
}
|
||||
System.out.println(threadId() + " " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopPhilosopher() {
|
||||
log("stopping");
|
||||
this.stop = true;
|
||||
interrupt();
|
||||
}
|
||||
|
||||
public Philosopher(int seat, Chopstick left, Chopstick right) {
|
||||
this.stop = false;
|
||||
this.seat = seat;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.random = new Random();
|
||||
this.eaten = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log("starting");
|
||||
try {
|
||||
while (!this.stop) {
|
||||
think();
|
||||
eat();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
log("stopped; eaten=" + this.eaten);
|
||||
}
|
||||
|
||||
private void think() throws InterruptedException {
|
||||
Thread.sleep(this.random.nextInt(MAX_THINKING_DURATION_MS));
|
||||
}
|
||||
|
||||
private void eat() throws InterruptedException {
|
||||
log("try taking left");
|
||||
synchronized (this.left) {
|
||||
log("left acquired");
|
||||
Thread.sleep(this.random.nextInt(MAX_TAKING_TIME_MS));
|
||||
log("try taking right");
|
||||
synchronized (this.right) {
|
||||
log("right acquired");
|
||||
log("eating");
|
||||
this.eaten++;
|
||||
Thread.sleep(this.random.nextInt(MAX_EATING_DURATION_MS));
|
||||
}
|
||||
log("right released");
|
||||
}
|
||||
log("left released");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package pp;
|
||||
|
||||
public class PhilosopherExperiment {
|
||||
|
||||
static final int PHILOSOPHER_NUM = 5;
|
||||
static final int EXP_DURATION_MS = 20000;
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var chopsticks = new Chopstick[PHILOSOPHER_NUM];
|
||||
var philosophers = new Philosopher[PHILOSOPHER_NUM];
|
||||
for (int i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
chopsticks[i] = new Chopstick();
|
||||
}
|
||||
// first n-1 philosophers
|
||||
for (var i = 0; i < (PHILOSOPHER_NUM - 1); i++) {
|
||||
philosophers[i] = new Philosopher(i, chopsticks[i], chopsticks[(i + 1)]);
|
||||
}
|
||||
// nth philosophers: initialize with right+left instead of left+right
|
||||
philosophers[PHILOSOPHER_NUM - 1] = new Philosopher(
|
||||
PHILOSOPHER_NUM - 1,
|
||||
chopsticks[0],
|
||||
chopsticks[PHILOSOPHER_NUM - 1]
|
||||
);
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
philosophers[i].start();
|
||||
}
|
||||
Thread.sleep(EXP_DURATION_MS);
|
||||
for (var i = 0; i < PHILOSOPHER_NUM; i++) {
|
||||
philosophers[i].stopPhilosopher();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "``wait``/``notifyAll`` für Ringpuffer"
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-02-BoundedQueueWaitNotify.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-waitnotifyall-für-ringpuffer)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.02-BoundedQueueWaitNotify</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.BoundedBuffer</exec.mainClass>
|
||||
<maven.compiler.release>10</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,82 @@
|
|||
package pp;
|
||||
|
||||
public class BoundedBuffer<T> {
|
||||
|
||||
final Object[] items = new Object[8];
|
||||
int putptr, takeptr, count;
|
||||
|
||||
public void put(T x) throws InterruptedException {
|
||||
// solange der Speicher voll ist, warten
|
||||
this.items[this.putptr] = x;
|
||||
if (++this.putptr == this.items.length) {
|
||||
this.putptr = 0;
|
||||
}
|
||||
++this.count;
|
||||
// nun ist etwas neues im Speicher: Alle wartenden Threads
|
||||
// benachrichtigen
|
||||
}
|
||||
|
||||
public T take() throws InterruptedException {
|
||||
// solange der Speicher leer ist, warten
|
||||
@SuppressWarnings("unchecked")
|
||||
var x = (T) this.items[this.takeptr];
|
||||
if (++this.takeptr == this.items.length) {
|
||||
this.takeptr = 0;
|
||||
}
|
||||
--this.count;
|
||||
// nun ist etwas Platz im Speicher: Alle wartenden Threads
|
||||
// benachrichtigen
|
||||
return x;
|
||||
}
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var mem = new BoundedBuffer<Integer>();
|
||||
var p1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-1"
|
||||
);
|
||||
var p2 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-2"
|
||||
);
|
||||
var c1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 20; j++) {
|
||||
System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Consumer-1"
|
||||
);
|
||||
var now = System.currentTimeMillis();
|
||||
p1.start();
|
||||
p2.start();
|
||||
c1.start();
|
||||
p1.join();
|
||||
p2.join();
|
||||
c1.join();
|
||||
System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "``wait``/``notifyAll`` für Ringpuffer"
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-02-BoundedQueueWaitNotify.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-waitnotifyall-für-ringpuffer)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.02-BoundedQueueWaitNotify_solution</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.BoundedBuffer</exec.mainClass>
|
||||
<maven.compiler.release>10</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,84 @@
|
|||
package pp;
|
||||
|
||||
public class BoundedBuffer<T> {
|
||||
|
||||
final Object[] items = new Object[8];
|
||||
int putptr, takeptr, count;
|
||||
|
||||
public synchronized void put(T x) throws InterruptedException {
|
||||
while (this.count == this.items.length) {
|
||||
wait();
|
||||
}
|
||||
this.items[this.putptr] = x;
|
||||
if (++this.putptr == this.items.length) {
|
||||
this.putptr = 0;
|
||||
}
|
||||
++this.count;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public synchronized T take() throws InterruptedException {
|
||||
while (this.count == 0) {
|
||||
wait();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
var x = (T) this.items[this.takeptr];
|
||||
if (++this.takeptr == this.items.length) {
|
||||
this.takeptr = 0;
|
||||
}
|
||||
--this.count;
|
||||
notifyAll();
|
||||
return x;
|
||||
}
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var mem = new BoundedBuffer<Integer>();
|
||||
var p1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-1"
|
||||
);
|
||||
var p2 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-2"
|
||||
);
|
||||
var c1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 20; j++) {
|
||||
System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Consumer-1"
|
||||
);
|
||||
var now = System.currentTimeMillis();
|
||||
p1.start();
|
||||
p2.start();
|
||||
c1.start();
|
||||
p1.join();
|
||||
p2.join();
|
||||
c1.join();
|
||||
System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "``await``/``signal`` für Ringpuffer”
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-03-BoundedQueueAwaitSignal.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-awaitsignal-für-ringpuffer)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.03-BoundedQueueAwaitSignal</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.BoundedBuffer</exec.mainClass>
|
||||
<maven.compiler.release>10</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,92 @@
|
|||
package pp;
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BoundedBuffer<T> {
|
||||
|
||||
final Lock lock = new ReentrantLock();
|
||||
final Condition notFull = this.lock.newCondition();
|
||||
final Condition notEmpty = this.lock.newCondition();
|
||||
|
||||
final Object[] items = new Object[8];
|
||||
int putptr, takeptr, count;
|
||||
|
||||
public void put(T x) throws InterruptedException {
|
||||
// solange der Speicher voll ist, warten
|
||||
this.items[this.putptr] = x;
|
||||
if (++this.putptr == this.items.length) {
|
||||
this.putptr = 0;
|
||||
}
|
||||
++this.count;
|
||||
// nun ist etwas neues im Speicher: Alle wartenden Threads
|
||||
// benachrichtigen
|
||||
}
|
||||
|
||||
public T take() throws InterruptedException {
|
||||
// solange der Speicher leer ist, mit der Bedingungsvariablen notEmpty
|
||||
// warten
|
||||
@SuppressWarnings("unchecked")
|
||||
var x = (T) this.items[this.takeptr];
|
||||
if (++this.takeptr == this.items.length) {
|
||||
this.takeptr = 0;
|
||||
}
|
||||
--this.count;
|
||||
// nun ist etwas Platz im Speicher: Alle für notFull wartenden Threads
|
||||
// benachrichtigen
|
||||
return x;
|
||||
}
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var mem = new BoundedBuffer<Integer>();
|
||||
var p1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-1"
|
||||
);
|
||||
var p2 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(Thread.currentThread().getName() + ": put=" + j);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Producer-2"
|
||||
);
|
||||
var c1 = new Thread(
|
||||
() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 20; j++) {
|
||||
System.out.println(Thread.currentThread().getName() + ": taken=" + mem.take());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
},
|
||||
"Consumer-1"
|
||||
);
|
||||
var now = System.currentTimeMillis();
|
||||
p1.start();
|
||||
p2.start();
|
||||
c1.start();
|
||||
p1.join();
|
||||
p2.join();
|
||||
c1.join();
|
||||
System.out.println("Runtime: " + (System.currentTimeMillis() - now) + "ms");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
# Laboraufgabe "``await``/``signal`` für Ringpuffer”
|
||||
- [Aufgabenstellung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-03-BoundedQueueAwaitSignal.html)
|
||||
- [Musterlösung](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/labs/03-Solutions.html#laboraufgabe-awaitsignal-für-ringpuffer)
|
||||
|
||||
# Materialien
|
||||
- [Folien](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/slides/03-steuerung.html)
|
||||
- [Skript](https://services.informatik.hs-mannheim.de/~s.leuchter/pp/notes/03-steuerung.html)
|
|
@ -0,0 +1,12 @@
|
|||
default:
|
||||
mvn clean compile exec:java
|
||||
exec args:
|
||||
mvn exec:java -Dexec.args={{args}}
|
||||
clean:
|
||||
mvn clean
|
||||
compile:
|
||||
mvn compile
|
||||
test:
|
||||
mvn test
|
||||
javadoc:
|
||||
mvn javadoc:javadoc
|
|
@ -0,0 +1,61 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pp</groupId>
|
||||
<artifactId>pp.03.03-BoundedQueueAwaitSignal_solution</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<exec.mainClass>pp.BoundedBuffer</exec.mainClass>
|
||||
<maven.compiler.release>10</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency><!-- für Unit-Tests -->
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für Lombok -->
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency><!-- für net.jcip Annotationen -->
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin><!-- für Unit-Tests [mvn test] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn compile] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.9.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn exec:java] -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin><!-- [mvn javadoc:javadoc] -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<show>private</show>
|
||||
<locale>en_US</locale>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,96 @@
|
|||
package pp;
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BoundedBuffer<T> {
|
||||
final Lock lock = new ReentrantLock();
|
||||
final Condition notFull = this.lock.newCondition();
|
||||
final Condition notEmpty = this.lock.newCondition();
|
||||
|
||||
final Object[] items = new Object[8];
|
||||
int putptr, takeptr, count;
|
||||
|
||||
public void put(T x) throws InterruptedException {
|
||||
this.lock.lock();
|
||||
try {
|
||||
while (this.count == this.items.length) {
|
||||
this.notFull.await(); // unlock falls Bedingung
|
||||
}
|
||||
this.items[this.putptr] = x;
|
||||
if (++this.putptr == this.items.length) {
|
||||
this.putptr = 0;
|
||||
}
|
||||
++this.count;
|
||||
this.notEmpty.signal();
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public T take() throws InterruptedException {
|
||||
this.lock.lock();
|
||||
try {
|
||||
while (this.count == 0) {
|
||||
this.notEmpty.await();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
var x = (T) this.items[this.takeptr];
|
||||
if (++this.takeptr == this.items.length) {
|
||||
this.takeptr = 0;
|
||||
}
|
||||
--this.count;
|
||||
this.notFull.signal();
|
||||
return x;
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) throws InterruptedException {
|
||||
var mem = new BoundedBuffer<Integer>();
|
||||
var p1 = new Thread(() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() + ": put=" + j);
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}, "Producer-1");
|
||||
var p2 = new Thread(() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 10; j++) {
|
||||
mem.put(j);
|
||||
System.out.println(
|
||||
Thread.currentThread().getName() + ": put=" + j);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}, "Producer-2");
|
||||
var c1 = new Thread(() -> {
|
||||
try {
|
||||
for (var j = 1; j <= 20; j++) {
|
||||
System.out.println(Thread.currentThread().getName()
|
||||
+ ": taken=" + mem.take());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}, "Consumer-1");
|
||||
var now = System.currentTimeMillis();
|
||||
p1.start();
|
||||
p2.start();
|
||||
c1.start();
|
||||
p1.join();
|
||||
p2.join();
|
||||
c1.join();
|
||||
System.out.println(
|
||||
"Runtime: " + (System.currentTimeMillis() - now) + "ms");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue