Universität Augsburg, Institut für Informatik Prof. Dr. Werner Kießling M. Endres, A. Huhn, T. Preisinger Sommersemester 2006 27. Juli. 2006 Lösungsblatt 13 Informatik II Aufgabe 1: Stoppuhr Stopwatch.java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Stopwatch extends JComponent implements ActionListener { Segment sec = new Segment(), secD = new Segment(), min = new Segment(), minD = new Segment(); JButton btnStart = new JButton("Start"), btnStop = new JButton("Stop"); StopwatchThread thread; public Stopwatch() { setLayout(new BorderLayout()); JPanel pnlValue = new JPanel(new GridLayout()); pnlValue.add(minD); pnlValue.add(min); pnlValue.add(new Segment(Segment.MINUS)); pnlValue.add(secD); pnlValue.add(sec); JPanel pnlControl = new JPanel(); pnlControl.add(btnStart); pnlControl.add(btnStop); add(pnlValue, BorderLayout.CENTER); add(pnlControl, BorderLayout.PAGE_END); btnStop.setEnabled(false); btnStart.addActionListener(this); btnStop.addActionListener(this); } public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if (src == btnStart) { // Start gedrückt btnStart.setEnabled(false); btnStop.setEnabled(true); // Thread starten thread = new StopwatchThread(); thread.start(); } else if (src == btnStop) { btnStart.setEnabled(true); btnStop.setEnabled(false); // Thread "anhalten" thread.pleaseStop(); thread = null; } } 1 public void setTime(int seconds) { sec.setValue(seconds % 10); seconds = seconds / 10; secD.setValue(seconds % 6); seconds = seconds / 6; min.setValue(seconds % 10); seconds = seconds / 10; minD.setValue(seconds % 10); repaint(); } class StopwatchThread extends Thread { boolean cont = true; long startTime; StopwatchThread() { this.setDaemon(true); } public void pleaseStop() { cont = false; } public void run() { startTime = System.currentTimeMillis(); while (cont) { // neuen Zählerstand berechnen und setzen int seconds = (int) (System.currentTimeMillis() - startTime) / 1000; setTime(seconds); // ... und warten try { sleep(1000);} catch (InterruptedException e) {} } } } } StopwatchApplet.java import javax.swing.JApplet; import javax.swing.JFrame; public class StopwatchApplet extends JApplet { public void init() { add(new Stopwatch()); validate(); } } stopwatch.html <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de"> <head> <title>Counter</title> <meta http-equiv="content-type" content="text/html;charset=iso-8859-1" /> </head> <body> <object classid="java:blatt13.StopwatchApplet" type="application/x-java-applet" height="200" width="450" codebase="file:."/> </body> </html> 2 Aufgabe 2: Fortschrittsanzeige mit Java 2D ProgressCircle.java import java.awt.*; import javax.swing.JComponent; public class ProgressCircle extends JComponent { // Minimum, Maximum und aktueller Wert int min, max, value; public ProgressCircle(int min, int max, int value) { this.min = min; this.max = max; this.value = value; } protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; Stroke standard = g2d.getStroke(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension dim = getSize(); // Breite und Höhe verringern, damit der Kreis komplett sichtbar ist. int width = (int) dim.getWidth() - 1; int height = (int) dim.getHeight() - 1; // Aussenkreis zeichnen g2d.drawOval(0, 0, width, height); // Innenkreis zeichnen // Zuerst Pinselfarbe ändern g2d.setPaint(new GradientPaint(0, 0, Color.YELLOW, width, height, Color.RED)); // Größentransformation und Translation durchführen double scaleFactor = ((double) value / max - min); g2d.translate(width / 2 * (1 - scaleFactor), height / 2 * (1 - scaleFactor)); g2d.scale(scaleFactor, scaleFactor); g2d.fillOval(1, 1, width - 2, height - 2); } public void setValue(int value) { this.value = value; } } ProgressCircleApplet.java public class ProgressCircleApplet extends JApplet { JSlider slider = new JSlider(0, 100, 0); ProgressCircle circle = new ProgressCircle(0, 100, 0); public void init() { setLayout(new BorderLayout()); slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { circle.setValue(slider.getValue()); circle.repaint(); } }); 3 slider.setPaintTicks(true); slider.setPaintLabels(true); slider.setMajorTickSpacing(10); slider.setMinorTickSpacing(2); add(circle, BorderLayout.CENTER); add(slider, BorderLayout.PAGE_END); } } Aufgabe 3: Erzeuger und Verbraucher in der Mensa Mensa.java import java.util.*; import java.util.concurrent.Semaphore; public class Mensa { public static void main(String[] args) { // Theke mit entsprechender Kapazität anlegen Theke theke = new Theke(100); // Threads initialisieren Angestellter[] personal = new Angestellter[5]; for (int i = 0; i < personal.length; i++) { personal[i] = new Angestellter(theke, i); } Student[] esser = new Student[100]; for (int i = 0; i < esser.length; i++) { esser[i] = new Student(theke);} // Threads starten for (Angestellter a : personal) a.start(); for (Student s : esser) s.start(); // Alle 2,5 Sekunden ausgeben, wie viele Personen im letzten // Intervall maximal warten mussten while (true) { // Maximal wartende ausgeben System.out " .println("\t\tMAXIMALE ZAHLEN: \n\t\t\tWartende Studenten: + theke.maxStudenten + "\n\t\t\tWartende Angestellte: " + theke.maxAngestellte + "\n\t\tWartezeit im Durchschnitt bei insgesamt " + theke.anzahlWarteVorgaenge + " Wartenden:\n\t\t\t" + ((theke.kummulierteWartezeit / 1000.0) / theke.anzahlWarteVorgaenge)); // Werte zurücksetzen theke.maxAngestellte = 0; theke.maxStudenten = 0; try { Thread.sleep(2500); } catch (InterruptedException e) {;} } } } 4 class Theke { /** * Sowohl für die verfügbaren Mahlzeiten als auch für die verfügbaren Plätze * auf der Theke sind Semaphore notwendig: Es darf nicht passieren, dass * weniger als 0 oder mehr als 100 Plätze auf der Theke belegt (also * Mahlzeiten verfügbar) sind. */ // Semaphor für die verfügbaren Mahlzeiten Semaphore mahlzeit; // Semaphor für die verfügbaren Plätze Semaphore platz; // die wartenden Personen Vector<Angestellter> wartendeAngestellte = new Vector<Angestellter>(); Vector<Student> wartendeStudenten = new Vector<Student>(); // die maximale Anzahl wartender Angestellter und Studenten int maxAngestellte; int maxStudenten; // Wartezeit long kummulierteWartezeit; int anzahlWarteVorgaenge; public Theke(int kapazitaet) { mahlzeit = new Semaphore(0, true); platz = new Semaphore(kapazitaet, true); } public void tablettAblegen(Angestellter a) throws InterruptedException { // Angestellter beginnt Warten - auf maximale Anzahl Wartender prüfen wartendeAngestellte.add(a); if (wartendeAngestellte.size() > maxAngestellte) maxAngestellte = wartendeAngestellte.size(); System.out.println("TA -start- Wartend (Studenten/Angestellte): (" + wartendeStudenten.size() + "/" + wartendeAngestellte.size() + "), " + "Verfügbare Mahlzeiten: " + mahlzeit.availablePermits()); // 50 Plätze auf der Theke belegen platz.acquire(50); // 50 Mahlzeiten zur Abholung durch Studenten freigeben mahlzeit.release(50); // wartendeAngestellte.remove(a); System.out.println("TA - end - Wartend (Studenten/Angestellte): (" + wartendeStudenten.size() + "/" + wartendeAngestellte.size() + "), " + "Verfügbare Mahlzeiten: " + mahlzeit.availablePermits()); } public void essenNehmen(Student s) throws InterruptedException { wartendeStudenten.add(s); if (wartendeStudenten.size() > maxStudenten) maxStudenten = wartendeStudenten.size(); System.out.println("EN -start- Wartend (Studenten/Angestellte): (" + wartendeStudenten.size() + "/" + wartendeAngestellte.size() + "), " + "Verfügbare Mahlzeiten: " + mahlzeit.availablePermits()); long start = System.currentTimeMillis(); // eine Mahlzeit nehmen mahlzeit.acquire(1); 5 // Wartezeitberechnung kummulierteWartezeit += System.currentTimeMillis() - start; anzahlWarteVorgaenge++; // einen Platz auf der Theke als frei markieren platz.release(1); // Student aus der Liste der Wartenden entfernen wartendeStudenten.remove(s); System.out.println("EN - end - Wartend (Studenten/Angestellte): (" + wartendeStudenten.size() + "/" + wartendeAngestellte.size() + "), " + "Verfügbare Mahlzeiten: " + mahlzeit.availablePermits()); } } class Student extends Thread { Theke theke; public Student(Theke theke) { this.theke = theke; } public void run() { while (true) { try { // eine Mahlzeit von der Theke nehmen theke.essenNehmen(this); // Wartezeit sleep(2000); } catch (InterruptedException e) {;} } } } class Angestellter extends Thread { Theke theke; int nummer; public Angestellter(Theke theke, int nummer) { this.theke = theke; this.nummer = nummer; } public void run() { while (true) { try { // neue Mahlzeiten auf die Theke legen theke.tablettAblegen(this); // Wartezeit sleep(5000); } catch (InterruptedException e) {;} } } } 6