Laboraufgaben für Kap. 3
parent
cdcb0c69fc
commit
dff9d7719f
|
@ -1,40 +1,41 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Sensor extends Thread {
|
public class Sensor extends Thread {
|
||||||
// eigentlich abstract
|
|
||||||
|
// eigentlich abstract
|
||||||
private final long frequency;
|
|
||||||
|
private final long frequency;
|
||||||
public Sensor(long frequency) {
|
|
||||||
this.frequency = frequency;
|
public Sensor(long frequency) {
|
||||||
start();
|
this.frequency = frequency;
|
||||||
}
|
start();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return the frequency
|
/**
|
||||||
*/
|
* @return the frequency
|
||||||
public long getFrequency() {
|
*/
|
||||||
return this.frequency;
|
public long getFrequency() {
|
||||||
}
|
return this.frequency;
|
||||||
|
}
|
||||||
protected String reading() {
|
|
||||||
// eigentlich abstract
|
protected String reading() {
|
||||||
return null;
|
// eigentlich abstract
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
while (true) {
|
public void run() {
|
||||||
System.out.println("reading: " + reading());
|
while (true) {
|
||||||
try {
|
System.out.println("reading: " + reading());
|
||||||
Thread.sleep(this.frequency);
|
try {
|
||||||
} catch (InterruptedException e) {
|
Thread.sleep(this.frequency);
|
||||||
Thread.currentThread().interrupt();
|
} catch (InterruptedException e) {
|
||||||
}
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static void main(String... args) {
|
|
||||||
var s = new Sensor(1000);
|
public static void main(String... args) {
|
||||||
}
|
var s = new Sensor(1000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class Thermometer extends Sensor {
|
public class Thermometer extends Sensor {
|
||||||
private final Random rand;
|
|
||||||
|
private final Random rand;
|
||||||
public Thermometer(long frequency) {
|
|
||||||
super(frequency);
|
public Thermometer(long frequency) {
|
||||||
this.rand = new Random();
|
super(frequency);
|
||||||
}
|
this.rand = new Random();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected String reading() {
|
@Override
|
||||||
return String.format("(%04d freq.): %3d°C", getFrequency(),
|
protected String reading() {
|
||||||
this.rand.nextInt(100));
|
return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
var s1 = new Thermometer(1000);
|
var s1 = new Thermometer(1000);
|
||||||
var s2 = new Thermometer(3000);
|
var s2 = new Thermometer(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,41 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Sensor extends Thread {
|
public class Sensor extends Thread {
|
||||||
// eigentlich abstract
|
|
||||||
|
// eigentlich abstract
|
||||||
private final long frequency;
|
|
||||||
|
private final long frequency;
|
||||||
public Sensor(long frequency) {
|
|
||||||
this.frequency = frequency;
|
public Sensor(long frequency) {
|
||||||
}
|
this.frequency = frequency;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @return the frequency
|
/**
|
||||||
*/
|
* @return the frequency
|
||||||
public long getFrequency() {
|
*/
|
||||||
return this.frequency;
|
public long getFrequency() {
|
||||||
}
|
return this.frequency;
|
||||||
|
}
|
||||||
protected String reading() {
|
|
||||||
// eigentlich abstract
|
protected String reading() {
|
||||||
return null;
|
// eigentlich abstract
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
while (true) {
|
public void run() {
|
||||||
System.out.println("reading: " + reading());
|
while (true) {
|
||||||
try {
|
System.out.println("reading: " + reading());
|
||||||
Thread.sleep(this.frequency);
|
try {
|
||||||
} catch (InterruptedException e) {
|
Thread.sleep(this.frequency);
|
||||||
Thread.currentThread().interrupt();
|
} catch (InterruptedException e) {
|
||||||
}
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public static void main(String... args) {
|
|
||||||
var s = new Sensor(1000);
|
public static void main(String... args) {
|
||||||
s.start();
|
var s = new Sensor(1000);
|
||||||
}
|
s.start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class Thermometer extends Sensor {
|
public class Thermometer extends Sensor {
|
||||||
private final Random rand;
|
|
||||||
|
private final Random rand;
|
||||||
public Thermometer(long frequency) {
|
|
||||||
super(frequency);
|
public Thermometer(long frequency) {
|
||||||
this.rand = new Random();
|
super(frequency);
|
||||||
}
|
this.rand = new Random();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
protected String reading() {
|
@Override
|
||||||
return String.format("(%04d freq.): %3d°C", getFrequency(),
|
protected String reading() {
|
||||||
this.rand.nextInt(100));
|
return String.format("(%04d freq.): %3d°C", getFrequency(), this.rand.nextInt(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
var s1 = new Thermometer(1000);
|
var s1 = new Thermometer(1000);
|
||||||
s1.start();
|
s1.start();
|
||||||
var s2 = new Thermometer(3000);
|
var s2 = new Thermometer(3000);
|
||||||
s2.start();
|
s2.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
class MyWorker implements Runnable {
|
class MyWorker implements Runnable {
|
||||||
private Thread self;
|
|
||||||
|
private Thread self;
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
while (true) {
|
this.self = Thread.currentThread();
|
||||||
System.out.println(
|
while (true) {
|
||||||
this.self.getName() + ": ID => " + this.self.threadId());
|
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
class MyWorkerCoop implements Runnable {
|
class MyWorkerCoop implements Runnable {
|
||||||
private Thread self;
|
|
||||||
|
private Thread self;
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
while (true) {
|
this.self = Thread.currentThread();
|
||||||
System.out.println(
|
while (true) {
|
||||||
this.self.getName() + ": ID => " + this.self.threadId());
|
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||||
Thread.yield();
|
Thread.yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Starter {
|
public class Starter {
|
||||||
static int WORKERS = 200;
|
|
||||||
|
static int WORKERS = 200;
|
||||||
public static void main(String... args) {
|
|
||||||
for (var i = 0; i < Starter.WORKERS; i++) {
|
public static void main(String... args) {
|
||||||
var t = new Thread(new MyWorker(), String.format("Worker-%03d", i));
|
for (var i = 0; i < Starter.WORKERS; i++) {
|
||||||
t.start();
|
var t = new Thread(new MyWorker(), String.format("Worker-%03d", i));
|
||||||
}
|
t.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
class MyWorker implements Runnable {
|
class MyWorker implements Runnable {
|
||||||
private Thread self;
|
|
||||||
|
private Thread self;
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
while (true) {
|
this.self = Thread.currentThread();
|
||||||
System.out.println(
|
while (true) {
|
||||||
this.self.getName() + ": ID => " + this.self.threadId());
|
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
class MyWorkerCoop implements Runnable {
|
class MyWorkerCoop implements Runnable {
|
||||||
private Thread self;
|
|
||||||
|
private Thread self;
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
while (true) {
|
this.self = Thread.currentThread();
|
||||||
System.out.println(
|
while (true) {
|
||||||
this.self.getName() + ": ID => " + this.self.threadId());
|
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||||
Thread.yield();
|
Thread.yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Starter {
|
public class Starter {
|
||||||
static int WORKERS = 200;
|
|
||||||
|
static int WORKERS = 200;
|
||||||
public static void main(String... args) {
|
|
||||||
for (var i = 0; i < Starter.WORKERS; i++) {
|
public static void main(String... args) {
|
||||||
var t = new Thread(new MyWorkerCoop(),
|
for (var i = 0; i < Starter.WORKERS; i++) {
|
||||||
String.format("Worker-%03d", i));
|
var t = new Thread(new MyWorkerCoop(), String.format("Worker-%03d", i));
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,26 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class StarterInner {
|
public class StarterInner {
|
||||||
static int WORKERS = 200;
|
|
||||||
|
static int WORKERS = 200;
|
||||||
public static void main(String... args) {
|
|
||||||
for (var i = 0; i < StarterInner.WORKERS; i++) {
|
public static void main(String... args) {
|
||||||
var t = new Thread(new Runnable() {
|
for (var i = 0; i < StarterInner.WORKERS; i++) {
|
||||||
private Thread self;
|
var t = new Thread(
|
||||||
|
new Runnable() {
|
||||||
@Override
|
private Thread self;
|
||||||
public void run() {
|
|
||||||
this.self = Thread.currentThread();
|
@Override
|
||||||
while (true) {
|
public void run() {
|
||||||
System.out.println(this.self.getName() + ": ID => "
|
this.self = Thread.currentThread();
|
||||||
+ this.self.threadId());
|
while (true) {
|
||||||
}
|
System.out.println(this.self.getName() + ": ID => " + this.self.threadId());
|
||||||
}
|
}
|
||||||
}, String.format("Worker-%03d", i));
|
}
|
||||||
t.start();
|
},
|
||||||
}
|
String.format("Worker-%03d", i)
|
||||||
}
|
);
|
||||||
}
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class StarterLambda {
|
public class StarterLambda {
|
||||||
static int WORKERS = 200;
|
|
||||||
|
static int WORKERS = 200;
|
||||||
public static void main(String... args) {
|
|
||||||
for (var i = 0; i < StarterLambda.WORKERS; i++) {
|
public static void main(String... args) {
|
||||||
var t = new Thread(() -> {
|
for (var i = 0; i < StarterLambda.WORKERS; i++) {
|
||||||
var self = Thread.currentThread();
|
var t = new Thread(
|
||||||
while (true) {
|
() -> {
|
||||||
System.out.println(
|
var self = Thread.currentThread();
|
||||||
self.getName() + ": ID => " + self.threadId());
|
while (true) {
|
||||||
}
|
System.out.println(self.getName() + ": ID => " + self.threadId());
|
||||||
}, String.format("Worker-%03d", i));
|
}
|
||||||
t.start();
|
},
|
||||||
}
|
String.format("Worker-%03d", i)
|
||||||
}
|
);
|
||||||
}
|
t.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Runner {
|
public class Runner {
|
||||||
public static void main(String... args) {
|
|
||||||
var task = new Task();
|
public static void main(String... args) {
|
||||||
var thread = new Thread(task);
|
var task = new Task();
|
||||||
thread.setUncaughtExceptionHandler((t, e) -> {
|
var thread = new Thread(task);
|
||||||
System.err.println("Unhandled Exception: " + e.getMessage());
|
thread.setUncaughtExceptionHandler((t, e) -> {
|
||||||
System.err.println(" Thread: " + t.threadId() + " - " + t.getName());
|
System.err.println("Unhandled Exception: " + e.getMessage());
|
||||||
System.err.println(" Thread State: " + t.getState());
|
System.err.println(" Thread: " + t.threadId() + " - " + t.getName());
|
||||||
e.printStackTrace(System.err);
|
System.err.println(" Thread State: " + t.getState());
|
||||||
});
|
e.printStackTrace(System.err);
|
||||||
thread.start();
|
});
|
||||||
}
|
thread.start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,36 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Task implements Runnable {
|
public class Task implements Runnable {
|
||||||
private volatile Thread self;
|
|
||||||
private volatile boolean stopped = false;
|
private volatile Thread self;
|
||||||
|
private volatile boolean stopped = false;
|
||||||
public void stopRequest() {
|
|
||||||
this.stopped = true;
|
public void stopRequest() {
|
||||||
if (this.self != null) {
|
this.stopped = true;
|
||||||
this.self.interrupt();
|
if (this.self != null) {
|
||||||
}
|
this.self.interrupt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public boolean isStopped() {
|
|
||||||
return this.stopped;
|
public boolean isStopped() {
|
||||||
}
|
return this.stopped;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
// 1. Initialisierungsphase
|
this.self = Thread.currentThread();
|
||||||
var i = 10;
|
// 1. Initialisierungsphase
|
||||||
while (!isStopped()) {
|
var i = 10;
|
||||||
// 2. Arbeitsphase
|
while (!isStopped()) {
|
||||||
System.out.println("i=" + i);
|
// 2. Arbeitsphase
|
||||||
try {
|
System.out.println("i=" + i);
|
||||||
Thread.sleep(1000 / i--);
|
try {
|
||||||
} catch (InterruptedException e) {
|
Thread.sleep(1000 / i--);
|
||||||
Thread.currentThread().interrupt();
|
} catch (InterruptedException e) {
|
||||||
}
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
// 3. Aufräumphase
|
}
|
||||||
System.out.println("fertig.");
|
// 3. Aufräumphase
|
||||||
}
|
System.out.println("fertig.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Runner {
|
public class Runner {
|
||||||
public static void main(String... args) {
|
|
||||||
var task = new Task();
|
public static void main(String... args) {
|
||||||
var thread = new Thread(task);
|
var task = new Task();
|
||||||
thread.setUncaughtExceptionHandler((t, e) -> {
|
var thread = new Thread(task);
|
||||||
System.err.println("Unhandled Exception: " + e.getMessage());
|
thread.setUncaughtExceptionHandler((t, e) -> {
|
||||||
System.err.println(" Thread: " + t.threadId() + " - " + t.getName());
|
System.err.println("Unhandled Exception: " + e.getMessage());
|
||||||
System.err.println(" Thread State: " + t.getState());
|
System.err.println(" Thread: " + t.threadId() + " - " + t.getName());
|
||||||
e.printStackTrace(System.err);
|
System.err.println(" Thread State: " + t.getState());
|
||||||
});
|
e.printStackTrace(System.err);
|
||||||
thread.start();
|
});
|
||||||
// falsch: thread läuft weiter:
|
thread.start();
|
||||||
// (new Thread(() -> thread.interrupt())).start();
|
// falsch: thread läuft weiter:
|
||||||
|
// (new Thread(() -> thread.interrupt())).start();
|
||||||
// richtig: thread wird beendet:
|
|
||||||
(new Thread(() -> task.stopRequest())).start();
|
// richtig: thread wird beendet:
|
||||||
}
|
(new Thread(() -> task.stopRequest())).start();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,35 +1,36 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class Task implements Runnable {
|
public class Task implements Runnable {
|
||||||
private volatile Thread self;
|
|
||||||
private volatile boolean stopped = false;
|
private volatile Thread self;
|
||||||
|
private volatile boolean stopped = false;
|
||||||
public void stopRequest() {
|
|
||||||
this.stopped = true;
|
public void stopRequest() {
|
||||||
if (this.self != null) {
|
this.stopped = true;
|
||||||
this.self.interrupt();
|
if (this.self != null) {
|
||||||
}
|
this.self.interrupt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public boolean isStopped() {
|
|
||||||
return this.stopped;
|
public boolean isStopped() {
|
||||||
}
|
return this.stopped;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
this.self = Thread.currentThread();
|
public void run() {
|
||||||
// 1. Initialisierungsphase
|
this.self = Thread.currentThread();
|
||||||
var i = 10;
|
// 1. Initialisierungsphase
|
||||||
while (!isStopped()) {
|
var i = 10;
|
||||||
// 2. Arbeitsphase
|
while (!isStopped()) {
|
||||||
System.out.println("i=" + i);
|
// 2. Arbeitsphase
|
||||||
try {
|
System.out.println("i=" + i);
|
||||||
Thread.sleep(1000 / i--);
|
try {
|
||||||
} catch (InterruptedException e) {
|
Thread.sleep(1000 / i--);
|
||||||
Thread.currentThread().interrupt();
|
} catch (InterruptedException e) {
|
||||||
}
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
// 3. Aufräumphase
|
}
|
||||||
System.out.println("fertig.");
|
// 3. Aufräumphase
|
||||||
}
|
System.out.println("fertig.");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,24 +1,22 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class MemoryBarrierTest extends Thread {
|
public class MemoryBarrierTest extends Thread {
|
||||||
|
|
||||||
public boolean stopped = false;
|
public boolean stopped = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!this.stopped) {
|
while (!this.stopped) {
|
||||||
// work
|
// work
|
||||||
}
|
}
|
||||||
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var t = new MemoryBarrierTest();
|
var t = new MemoryBarrierTest();
|
||||||
t.start();
|
t.start();
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
t.stopped = true;
|
t.stopped = true;
|
||||||
System.out.println(
|
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,26 +1,24 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class MemoryBarrierTest1 extends Thread {
|
public class MemoryBarrierTest1 extends Thread {
|
||||||
|
|
||||||
// Markierung von stopped als volatile => Jede Änderung wirkt als
|
// Markierung von stopped als volatile => Jede Änderung wirkt als
|
||||||
// Memory-Barrier
|
// Memory-Barrier
|
||||||
public volatile boolean stopped = false;
|
public volatile boolean stopped = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!this.stopped) {
|
while (!this.stopped) {
|
||||||
// work
|
// work
|
||||||
}
|
}
|
||||||
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var t = new MemoryBarrierTest1();
|
var t = new MemoryBarrierTest1();
|
||||||
t.start();
|
t.start();
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
t.stopped = true;
|
t.stopped = true;
|
||||||
System.out.println(
|
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,8 +29,6 @@ public class MemoryBarrierTest1b extends Thread {
|
||||||
t.start();
|
t.start();
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
t.setStopped(true);
|
t.setStopped(true);
|
||||||
System.out.println(
|
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class MemoryBarrierTest2 extends Thread {
|
public class MemoryBarrierTest2 extends Thread {
|
||||||
|
|
||||||
public boolean stopped = false;
|
public boolean stopped = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!this.stopped) {
|
while (!this.stopped) {
|
||||||
// jedes synchronized wirkt als Memory-Barrier
|
// jedes synchronized wirkt als Memory-Barrier
|
||||||
// work
|
// work
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var t = new MemoryBarrierTest2();
|
var t = new MemoryBarrierTest2();
|
||||||
t.start();
|
t.start();
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
t.stopped = true;
|
t.stopped = true;
|
||||||
System.out.println(
|
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ public class MemoryBarrierTest5 extends Thread {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
this.stopped = true;
|
this.stopped = true;
|
||||||
System.out.println(
|
System.out.println("Stopper thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Stopper thread set stopped on MemoryBarrierTest-Thread.");
|
|
||||||
});
|
});
|
||||||
this.stopper.start();
|
this.stopper.start();
|
||||||
}
|
}
|
||||||
|
@ -40,7 +39,5 @@ public class MemoryBarrierTest5 extends Thread {
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var t = new MemoryBarrierTest5();
|
var t = new MemoryBarrierTest5();
|
||||||
t.start();
|
t.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
public class MemoryBarrierTest6 extends Thread {
|
public class MemoryBarrierTest6 extends Thread {
|
||||||
|
|
||||||
public boolean stopped = false;
|
public boolean stopped = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (!this.stopped) {
|
while (!this.stopped) {
|
||||||
// work
|
// work
|
||||||
// wg. Zustandswechsel
|
// wg. Zustandswechsel
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
System.out.println("MemoryBarrierTest-Thread actually stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var t = new MemoryBarrierTest6();
|
var t = new MemoryBarrierTest6();
|
||||||
t.start();
|
t.start();
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
t.stopped = true;
|
t.stopped = true;
|
||||||
System.out.println(
|
System.out.println("Main thread set stopped on MemoryBarrierTest-Thread.");
|
||||||
"Main thread set stopped on MemoryBarrierTest-Thread.");
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class MyThreadLocalRandom0 implements Runnable {
|
public class MyThreadLocalRandom0 implements Runnable {
|
||||||
public static long now = System.currentTimeMillis();
|
|
||||||
public Random rand = new Random(now);
|
public static long now = System.currentTimeMillis();
|
||||||
|
public Random rand = new Random(now);
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
var strBuf = new StringBuffer();
|
public void run() {
|
||||||
strBuf.append(Thread.currentThread().getName() + ": ");
|
var strBuf = new StringBuffer();
|
||||||
for (var j = 0; j < 20; j++) {
|
strBuf.append(Thread.currentThread().getName() + ": ");
|
||||||
strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
|
for (var j = 0; j < 20; j++) {
|
||||||
}
|
strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
|
||||||
System.out.println(strBuf);
|
}
|
||||||
}
|
System.out.println(strBuf);
|
||||||
|
}
|
||||||
public static void main(String... args) {
|
|
||||||
var runner = new MyThreadLocalRandom0();
|
public static void main(String... args) {
|
||||||
for (var i = 0; i < 10; i++) {
|
var runner = new MyThreadLocalRandom0();
|
||||||
new Thread(runner, String.format("Runner-%02d", i)).start();
|
for (var i = 0; i < 10; i++) {
|
||||||
}
|
new Thread(runner, String.format("Runner-%02d", i)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,30 +1,31 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class MyThreadLocalRandom1 implements Runnable {
|
public class MyThreadLocalRandom1 implements Runnable {
|
||||||
public static long now = System.currentTimeMillis();
|
|
||||||
public ThreadLocal<Random> rand = new ThreadLocal<>() {
|
public static long now = System.currentTimeMillis();
|
||||||
@Override
|
public ThreadLocal<Random> rand = new ThreadLocal<>() {
|
||||||
protected Random initialValue() {
|
@Override
|
||||||
return new Random(now);
|
protected Random initialValue() {
|
||||||
}
|
return new Random(now);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
var strBuf = new StringBuffer();
|
public void run() {
|
||||||
strBuf.append(Thread.currentThread().getName() + ": ");
|
var strBuf = new StringBuffer();
|
||||||
for (var j = 0; j < 20; j++) {
|
strBuf.append(Thread.currentThread().getName() + ": ");
|
||||||
strBuf.append(String.format("%02d ", this.rand.get().nextInt(100)));
|
for (var j = 0; j < 20; j++) {
|
||||||
}
|
strBuf.append(String.format("%02d ", this.rand.get().nextInt(100)));
|
||||||
System.out.println(strBuf);
|
}
|
||||||
}
|
System.out.println(strBuf);
|
||||||
|
}
|
||||||
public static void main(String... args) {
|
|
||||||
var runner = new MyThreadLocalRandom1();
|
public static void main(String... args) {
|
||||||
for (var i = 0; i < 10; i++) {
|
var runner = new MyThreadLocalRandom1();
|
||||||
new Thread(runner, String.format("Runner-%02d", i)).start();
|
for (var i = 0; i < 10; i++) {
|
||||||
}
|
new Thread(runner, String.format("Runner-%02d", i)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,30 +1,31 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class MyThreadLocalRandom2 implements Runnable {
|
public class MyThreadLocalRandom2 implements Runnable {
|
||||||
public static long now = System.currentTimeMillis();
|
|
||||||
public static ThreadLocal<Random> rand = new ThreadLocal<>() {
|
public static long now = System.currentTimeMillis();
|
||||||
@Override
|
public static ThreadLocal<Random> rand = new ThreadLocal<>() {
|
||||||
protected Random initialValue() {
|
@Override
|
||||||
return new Random(now);
|
protected Random initialValue() {
|
||||||
}
|
return new Random(now);
|
||||||
};
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public void run() {
|
@Override
|
||||||
var strBuf = new StringBuffer();
|
public void run() {
|
||||||
strBuf.append(Thread.currentThread().getName() + ": ");
|
var strBuf = new StringBuffer();
|
||||||
for (var j = 0; j < 20; j++) {
|
strBuf.append(Thread.currentThread().getName() + ": ");
|
||||||
strBuf.append(String.format("%02d ", rand.get().nextInt(100)));
|
for (var j = 0; j < 20; j++) {
|
||||||
}
|
strBuf.append(String.format("%02d ", rand.get().nextInt(100)));
|
||||||
System.out.println(strBuf);
|
}
|
||||||
}
|
System.out.println(strBuf);
|
||||||
|
}
|
||||||
public static void main(String... args) {
|
|
||||||
var runner = new MyThreadLocalRandom2();
|
public static void main(String... args) {
|
||||||
for (var i = 0; i < 10; i++) {
|
var runner = new MyThreadLocalRandom2();
|
||||||
new Thread(runner, String.format("Runner-%02d", i)).start();
|
for (var i = 0; i < 10; i++) {
|
||||||
}
|
new Thread(runner, String.format("Runner-%02d", i)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class MyThreadLocalRandom3 implements Runnable {
|
public class MyThreadLocalRandom3 implements Runnable {
|
||||||
|
|
||||||
public static Random rand = ThreadLocalRandom.current();
|
public static Random rand = ThreadLocalRandom.current();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
var strBuf = new StringBuffer();
|
var strBuf = new StringBuffer();
|
||||||
strBuf.append(Thread.currentThread().getName() + ": ");
|
strBuf.append(Thread.currentThread().getName() + ": ");
|
||||||
for (var j = 0; j < 20; j++) {
|
for (var j = 0; j < 20; j++) {
|
||||||
synchronized (MyThreadLocalRandom3.class) {
|
synchronized (MyThreadLocalRandom3.class) {
|
||||||
strBuf.append(String.format("%02d ", rand.nextInt(100)));
|
strBuf.append(String.format("%02d ", rand.nextInt(100)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println(strBuf);
|
System.out.println(strBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var runner = new MyThreadLocalRandom3();
|
var runner = new MyThreadLocalRandom3();
|
||||||
for (var i = 0; i < 10; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
new Thread(runner, String.format("Runner-%02d", i)).start();
|
new Thread(runner, String.format("Runner-%02d", i)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
package pp;
|
package pp;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class MyThreadLocalRandom4 implements Runnable {
|
public class MyThreadLocalRandom4 implements Runnable {
|
||||||
|
|
||||||
public Random rand = ThreadLocalRandom.current();
|
public Random rand = ThreadLocalRandom.current();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
var strBuf = new StringBuffer();
|
var strBuf = new StringBuffer();
|
||||||
strBuf.append(Thread.currentThread().getName() + ": ");
|
strBuf.append(Thread.currentThread().getName() + ": ");
|
||||||
for (var j = 0; j < 20; j++) {
|
for (var j = 0; j < 20; j++) {
|
||||||
synchronized (MyThreadLocalRandom4.class) {
|
synchronized (MyThreadLocalRandom4.class) {
|
||||||
strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
|
strBuf.append(String.format("%02d ", this.rand.nextInt(100)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.out.println(strBuf);
|
System.out.println(strBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String... args) throws InterruptedException {
|
public static void main(String... args) throws InterruptedException {
|
||||||
var runner = new MyThreadLocalRandom4();
|
var runner = new MyThreadLocalRandom4();
|
||||||
for (var i = 0; i < 10; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
new Thread(runner, String.format("Runner-%02d", i)).start();
|
new Thread(runner, String.format("Runner-%02d", i)).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,7 @@ public class Factory {
|
||||||
() -> {
|
() -> {
|
||||||
Type object = Factory.getInstance();
|
Type object = Factory.getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
String.format("InstanceGrabber-%02d", i)
|
||||||
|
|
|
@ -20,9 +20,7 @@ public class Factory0 {
|
||||||
() -> {
|
() -> {
|
||||||
var object = getInstance();
|
var object = getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
String.format("InstanceGrabber-%02d", i)
|
||||||
|
|
|
@ -20,9 +20,7 @@ public class Factory1 {
|
||||||
() -> {
|
() -> {
|
||||||
var object = getInstance();
|
var object = getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
String.format("InstanceGrabber-%02d", i)
|
||||||
|
|
|
@ -22,9 +22,7 @@ public class Factory2 {
|
||||||
() -> {
|
() -> {
|
||||||
var object = getInstance();
|
var object = getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
String.format("InstanceGrabber-%02d", i)
|
||||||
|
|
|
@ -23,9 +23,7 @@ public class Factory3 {
|
||||||
() -> {
|
() -> {
|
||||||
var object = Factory3.getInstance();
|
var object = Factory3.getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
String.format("InstanceGrabber-%02d", i)
|
||||||
|
|
|
@ -24,9 +24,7 @@ public class Factory4 {
|
||||||
() -> {
|
() -> {
|
||||||
var object = getInstance();
|
var object = getInstance();
|
||||||
System.out.println(
|
System.out.println(
|
||||||
Thread.currentThread().getName() +
|
Thread.currentThread().getName() + ": serial of instance = " + object.getSerial()
|
||||||
": serial of instance = " +
|
|
||||||
object.getSerial()
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
String.format("InstanceGrabber-%02d", i)
|
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