diff --git a/README.adoc b/README.adoc index 23873ba..45586af 100644 --- a/README.adoc +++ b/README.adoc @@ -81,6 +81,22 @@ Die Pflichtaufgabe wird mit 0 bis 2 Punkten bewertet (siehe _Leistungsnachweise_ .Thread Zustandsmodell (vereinfacht) image::Thread-State-Model.png[pdfwidth=80%, width=900px] +==== Instanz einer Subklasse von Thread erstellen. +- muss Methode run() beinhalten. +- erstellen mit Thread myThread = new MyThread(); +- starten mit new MyThread().start(); + +==== Interface Runnable implementieren +- muss Methode run() beinhalten. +- starten mit new Thread(new MyRunnable()).start(); + +==== Zustandswechsel +- Ready sobald run() aufgerufen wird. +- Running sobald scheduler den Thread ausführt. +- Zurück zu Ready mit t.yield() wird durch scheduler ausgeführt. +- manuell pausieren mit: t.join(), t.sleep(time), t.join(timeout) +- endet automatisch sobald die Methode run() fertig ausgeführt ist. + === Printer-Threads: Verwendung von Java Threads [PU] Nachfolgend einige Basisübungen zum Starten und Stoppen von Threads in Java. @@ -154,8 +170,11 @@ Wenn nötig, geben Sie auch die Konfiguration des Thread-Pools an. [loweralpha] . Sie schreiben einen Server, der via Netzwerk Anfragen erhält. Jede Anfrage soll in einem eigenen Task beantwortet werden. Die Anzahl gleichzeitiger Anfragen schwankt über den Tag verteilt stark. +- CachedThreadPool . Ihr Graphikprogramm verwendet komplexe Mathematik um von hunderten von Objekten die Position, Geschwindigkeit und scheinbare Grösse (aus Sicht des Betrachters) zu berechnen und auf dem Bildschirm darzustellen. +- SingleThreadExecutor . Je nach Datenset sind unterschiedliche Algorithmen schneller in der Berechnung des Resultats (z.B. Sortierung). Sie möchten jedoch in jedem Fall immer so schnell wie möglich das Resultat haben und lassen deshalb mehrere Algorithmen parallel arbeiten. +- FixedThreadPool === Prime Checker [PU] diff --git a/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotCallableProcessor.java b/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotCallableProcessor.java index 56d9155..82d746c 100644 --- a/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotCallableProcessor.java +++ b/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotCallableProcessor.java @@ -11,6 +11,7 @@ import java.util.concurrent.*; public class MandelbrotCallableProcessor extends MandelbrotProcessor { private volatile boolean terminate; // signal the threads to abort processing and terminate + ExecutorService executorService; /** * Initialize the Mandelbrot processor. @@ -38,9 +39,13 @@ public class MandelbrotCallableProcessor extends MandelbrotProcessor { super.startTime = System.currentTimeMillis(); // TODO: Start the the executor service with the given number of threads. + executorService = Executors.newFixedThreadPool(numThreads); // TODO: process all rows using the Callable MandelbrotTask and store returned Futures in a list - + List> futures = new ArrayList<>(); + for(int row = 0; row < height; row ++) { + futures.add(executorService.submit(new MandelbrotTask(row))); + } @@ -51,11 +56,14 @@ public class MandelbrotCallableProcessor extends MandelbrotProcessor { // TODO: get results from Future list and send them to the processListener (GUI) // make sure to handle all Exceptions try { + for(Future future : futures) { + processorListener.rowProcessed(future.get()); + } - - - - + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); } finally { // stop processing and shutdown executor stopProcessing(); @@ -70,7 +78,7 @@ public class MandelbrotCallableProcessor extends MandelbrotProcessor { public void stopProcessing() { terminate = true; // signal the threads to abort // TODO: shutdown executor service - + executorService.shutdown(); // calculate processing time @@ -93,10 +101,49 @@ public class MandelbrotCallableProcessor extends MandelbrotProcessor { private class MandelbrotTask implements Callable { // TODO: Use Task implementation from MandelbrotExecutorProcessor change it to a Callable. + private final int row; + private final double xmin, xmax, ymin, ymax, dx, dy; + private final int maxIterations; - public ImageRow call() { - return null; // Compute one row of pixels. + MandelbrotTask(int row) { + this.row = row; + xmin = -1.6744096740931858; + xmax = -1.674409674093473; + ymin = 4.716540768697223E-5; + ymax = 4.716540790246652E-5; + dx = (xmax - xmin) / (width - 1); + dy = (ymax - ymin) / (height - 1); + maxIterations = 10000; } + @Override + public ImageRow call() { + // Compute one row of pixels. + + final ImageRow imageRow = new ImageRow(row, width); + double x; + double y = ymax - dy * row; + + for (int col = 0; col < width; col++) { + x = xmin + dx * col; + int count = 0; + double xx = x; + double yy = y; + while (count < maxIterations && (xx * xx + yy * yy) < 4) { + count++; + double newxx = xx * xx - yy * yy + x; + yy = 2 * xx * yy + y; + xx = newxx; + } + // select color based on count of iterations + imageRow.pixels[col] = (count != maxIterations) ? + palette[count % palette.length] : Color.BLACK; + + } + return imageRow; + } + + + } // end MandelbrotTask } diff --git a/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotExecutorProcessor.java b/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotExecutorProcessor.java index 3c01375..b83bf14 100644 --- a/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotExecutorProcessor.java +++ b/code/Mandelbrot/src/main/java/ch/zhaw/prog2/mandelbrot/processors/MandelbrotExecutorProcessor.java @@ -10,7 +10,7 @@ import java.util.concurrent.Executors; public class MandelbrotExecutorProcessor extends MandelbrotProcessor { private volatile boolean terminate; // signal the threads to abort processing and terminate - + private ExecutorService executorService; /** * Initialize the Mandelbrot processor. @@ -39,8 +39,17 @@ public class MandelbrotExecutorProcessor extends MandelbrotProcessor { // TODO: Start the the executor service with the given number of threads. + executorService = Executors.newFixedThreadPool(numThreads); + // TODO: start a task for each row + for(int row = 0; row < height; row ++) { + + executorService.execute(new MandelbrotExecutorProcessor.MandelbrotTask(row)); + + } + + @@ -54,6 +63,7 @@ public class MandelbrotExecutorProcessor extends MandelbrotProcessor { public void stopProcessing() { terminate = true; // signal the threads to abort // TODO: shutdown executor service + executorService.shutdown(); // calculate processing time long duration = System.currentTimeMillis() - startTime; @@ -72,9 +82,45 @@ public class MandelbrotExecutorProcessor extends MandelbrotProcessor { private class MandelbrotTask implements Runnable { // TODO: Use Task implementation from MandelbrotTaskProcessor and modify it to calculat only one row. + private final int row; + private final double xmin, xmax, ymin, ymax, dx, dy; + private final int maxIterations; + + MandelbrotTask(int row) { + this.row = row; + xmin = -1.6744096740931858; + xmax = -1.674409674093473; + ymin = 4.716540768697223E-5; + ymax = 4.716540790246652E-5; + dx = (xmax - xmin) / (width - 1); + dy = (ymax - ymin) / (height - 1); + maxIterations = 10000; + } + @Override public void run() { + final ImageRow imageRow = new ImageRow(row, width); + double x; + double y = ymax - dy * row; + for (int col = 0; col < width; col++) { + x = xmin + dx * col; + int count = 0; + double xx = x; + double yy = y; + while (count < maxIterations && (xx * xx + yy * yy) < 4) { + count++; + double newxx = xx * xx - yy * yy + x; + yy = 2 * xx * yy + y; + xx = newxx; + } + // select color based on count of iterations + imageRow.pixels[col] = (count != maxIterations) ? + palette[count % palette.length] : Color.BLACK; + + } + processorListener.rowProcessed(imageRow); + taskFinished(); } } // end MandelbrotTask } diff --git a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeChecker.java b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeChecker.java index 76e6e42..9036ecf 100644 --- a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeChecker.java +++ b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeChecker.java @@ -21,7 +21,7 @@ public class PrimeChecker { private static void checkPrimes(int numPrimes) throws InterruptedException { for (int i = 0; i < numPrimes; i++) { - new PrimeTask(nextRandom()).run(); // runs sequential in current thread + new Thread(new PrimeTask(nextRandom())).start(); // runs sequential in current thread } } diff --git a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerExecutor.java b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerExecutor.java index aa390c4..423d0c2 100644 --- a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerExecutor.java +++ b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerExecutor.java @@ -2,6 +2,7 @@ package ch.zhaw.prog2.primechecker; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class PrimeCheckerExecutor { @@ -25,15 +26,16 @@ public class PrimeCheckerExecutor { private static void checkPrimes(int numPrimes) throws InterruptedException { // TODO: create ExecutorService - What ThreadPool-Type/-Size fits best? - + ExecutorService executor = Executors.newFixedThreadPool(12); for (int i = 0; i < numPrimes; i++) { // TODO: execute the runnable using the executor service + executor.execute(new PrimeTask(nextRandom())); } - // stop ExecutorService - - // wait for termination with timeout of 1 minute - + // TODO: stop ExecutorService + executor.shutdown(); + // TODO: wait for termination with timeout of 1 minute + executor.awaitTermination(1, TimeUnit.MINUTES); } private static long nextRandom() { diff --git a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerFuture.java b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerFuture.java index a871611..53b24b3 100644 --- a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerFuture.java +++ b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeCheckerFuture.java @@ -25,19 +25,26 @@ public class PrimeCheckerFuture { private static void checkPrimes(int numPrimes) throws InterruptedException { // TODO: create ExecutorService - + ExecutorService executor = Executors.newFixedThreadPool(12); // TODO: submit tasks to ExecutorService and collect the returned Futures in a List + List> futures = new ArrayList<>(); for (int i = 0; i < numPrimes; i++) { - + futures.add(executor.submit(new PrimeTaskCallable(nextRandom()))); } // TODO: Loop through List, wait for completion and print results - + for(Future future : futures){ + try { + System.out.println(future.get()); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } // TODO: stop ExecutorService - + executor.shutdown(); // TODO: await termination with timeout 1 minute - + executor.awaitTermination(1, TimeUnit.MINUTES); } private static long nextRandom() { diff --git a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeTaskCallable.java b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeTaskCallable.java index e29f293..a4a7f51 100644 --- a/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeTaskCallable.java +++ b/code/PrimeChecker/src/main/java/ch/zhaw/prog2/primechecker/PrimeTaskCallable.java @@ -12,7 +12,7 @@ public class PrimeTaskCallable implements Callable { public Result call() { - return null; + return new Result(primeCandidate, findSmallestFactor(primeCandidate)); } /** @@ -47,5 +47,14 @@ public class PrimeTaskCallable implements Callable { this.factor = factor; this.isPrime = factor == 0; } + + @Override + public String toString() { + return "Result{" + + "candidate=" + candidate + + ", factor=" + factor + + ", isPrime=" + isPrime + + '}'; + } } } diff --git a/code/Printer/src/main/java/ch/zhaw/prog2/printer/Printer.java b/code/Printer/src/main/java/ch/zhaw/prog2/printer/Printer.java index 8d2be19..9b1088f 100644 --- a/code/Printer/src/main/java/ch/zhaw/prog2/printer/Printer.java +++ b/code/Printer/src/main/java/ch/zhaw/prog2/printer/Printer.java @@ -15,6 +15,7 @@ public class Printer { private static class PrinterThread extends Thread { char symbol; int sleepTime; + Thread current_thread = this; public PrinterThread(String name, char symbol, int sleepTime) { super(name); @@ -24,6 +25,9 @@ public class Printer { @Override public void run() { + if(Thread.currentThread() != current_thread){ + return; + } System.out.println(getName() + " run started..."); for (int i = 1; i < 100; i++) { System.out.print(symbol); diff --git a/code/Printer/src/main/java/ch/zhaw/prog2/printer/PrinterB.java b/code/Printer/src/main/java/ch/zhaw/prog2/printer/PrinterB.java new file mode 100644 index 0000000..c434cd1 --- /dev/null +++ b/code/Printer/src/main/java/ch/zhaw/prog2/printer/PrinterB.java @@ -0,0 +1,45 @@ +package ch.zhaw.prog2.printer; + +public class PrinterB { + + // test program + public static void main(String[] arg) throws InterruptedException { + Thread threadA = new Thread(new PrinterRunnable("PrinterA", '.', 10)); + threadA.start(); + + Thread threadB = new Thread(new PrinterRunnable("PrinterB", '*', 20)); + threadB.start(); + + while(threadA.isAlive() || threadB.isAlive()){ + Thread.sleep(10); + } + System.out.println("Ende Main Thread asdf"); + } + + + private static class PrinterRunnable implements Runnable { + char symbol; + int sleepTime; + String name; + + public PrinterRunnable(String name, char symbol, int sleepTime) { + this.name = name; + this.symbol = symbol; + this.sleepTime = sleepTime; + } + + @Override + public void run() { + System.out.println(name + " run started..."); + for (int i = 1; i < 100; i++) { + System.out.print(symbol); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + } + System.out.println('\n' + name + " run ended."); + } + } +}