# Warten auf Events



## taouri (7. Oktober 2006)

Hallo,

also ich hätte folgendes Problem: Ich muss in einem Programm warten, bis ein bestimmtes Event ausgelöst wurde. Ist es möglich den Programmfluss solange zu unterbrechen? Mit Thread.join() und SwingUtilites.invokeAndWait(Runnable run) hab ichs schon erfolglos versucht. Kann mir bitte jemand helfen?

Gruß

taouri


----------



## RealHAZZARD (7. Oktober 2006)

Servus
Initialisiete dein Programm, registriere den Listener den du brauchst, und wenn du warten willst machst du folgendes:

```
synchronized (this){
            try {
                this.wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
```

Wenn dein Event stattfindet muss folgendes gemacht werden:

```
this.notify();
```

btw: das wait und notify kommt vom Object.


----------



## taouri (8. Oktober 2006)

hi,

Im ersten Moment wirkt das wirklich gut. Aber sobald das notify ausgelöst wird folgt eine IllegalMonitorStateException. Bist du sicher, dass das der exakte Quellcode ist? muss vielleicht der Listener das Flag setzen? Also listener.notify() ?

Gruß

taouri


----------



## Thomas Darimont (8. Oktober 2006)

Hallo!

Ich denke du solltest erst nochmal genau erklären was du vor hast... ich finds nicht so schlau die ganze Anwendung schlafen zu legen / zu blockieren wenn du auf ein Event in der GUI wartest...



> Im ersten Moment wirkt das wirklich gut. Aber sobald das notify ausgelöst wird folgt eine IllegalMonitorStateException. Bist du sicher, dass das der exakte Quellcode ist? muss vielleicht der Listener das Flag setzen? Also listener.notify() ?



Wenn du notfiy an einem Objekt aufrufen willst mußt du auch den Monitor auf das Objekt haben...

hier mal ein einfaches Producer/Consumer Szenario unter Java 1.4 welches zeigt wie man mit wait() / notify() umgeht (Hierbei produziert der Producer immer nur ein Objekt und wartet so lange bis der Consumer das gerade produzierte Objekt konsumiert hat):

```
/**
 * 
 */
package de.tutorials;

/**
 * @author Tom
 * 
 */
public class ThreadingExample {

    static Object mutex = new Object();

    static String result;

    /**
     * @param args
     */
    public static void main(String[] args) {
        Thread producer = new Thread("Producer") {
            public void run() {
                while (true) {
                    synchronized (mutex) {
                        log("Produces something.");
                        result = produce();
                        log("Produced " + result);
                        try {
                            mutex.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            private String produce() {
                try {
                    sleep(5000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return String.valueOf(System.currentTimeMillis());

            }
        };
        Thread consumer = new Thread("Consumer") {
            @Override
            public void run() {
                while (true) {
                    log("Waiting for something to consume");
                    synchronized (mutex) {
                        consume();
                        mutex.notify();
                    }
                }
            }

            private void consume() {
                log("Consume " + result);
            }
        };

        producer.start();
        consumer.start();
    }

    protected static void log(String string) {
        System.out.println("[" + System.currentTimeMillis() + "] "
                + Thread.currentThread().getName() + ": " + string);
    }

}
```

Unter Java 5 geht das natürlich viel einfacher ;-)

Gruß Tom


----------



## taouri (8. Oktober 2006)

Hi,

Puh, leider beschäftige ich mich zum ersten Mal mit dem Producer/Consumer Pattern. 
Also mein Problem sieht folgendermaßen aus:
Ich habe eine Methode die ein Objekt einer Klasse erzeugt. Im Konstruktor dieser Klasse wird dann eine GUI-Anwendung aufgerufen in der Angaben gemacht werde, die sobald in der GUI der OK Button gedrückt wurde an das Klassen-Objekt geliefert werden. Erst danach, soll in der eigentlichen Methode eine Methode der Klasse aufgerufen werden, die den Vorgang wiederholt (wiederum durch ein Event). Und zu allem Überdruss muss zwischendrin auch noch mit den Informationen der Klasse die zweite GUI-Anwendung gefüttert werden. 
Mein Problem ist also, dass ich solange mit dem Öffnen der zweiten Anwendung warten muss, bis das Klassen-Objekt die nötigen Informationen aus der ersten Anwendung erhalten hat. Klingt kompliziert, wie komplex es wirklich ist, weiß ich aber nich ;-) .

Gruß

taouri


----------



## RealHAZZARD (8. Oktober 2006)

Thomas Darimont hat gesagt.:


> Unter Java 5 geht das natürlich viel einfacher ;-)



Kannst du mir bitte erklären, wie es unter Java 5 aussieht? (Will ja dazulernen)


----------



## Thomas Darimont (8. Oktober 2006)

Hallo!



> Zitat:
> Zitat von *Thomas Darimont*
> 
> 
> ...



Schau mal hier:

```
/**
 * 
 */
package de.tutorials;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Tom
 * 
 */
public class ProducerConsumer {

    /**
     * @param args
     */
    public static void main(String[] args) {
        final Lock lock = new ReentrantLock();

        final BlockingQueue<String> productionBelt = new ArrayBlockingQueue<String>(
                10);

        Runnable producer = new Runnable() {
            public void run() {
                while (true) {
                    String item = produce();
                    System.out.println("Produced: " + item);
                    productionBelt.add(item);
                }
            }

            private String produce() {
                try {
                    TimeUnit.SECONDS.sleep(5L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return String.valueOf(System.currentTimeMillis());
            }
        };

        Runnable consumer = new Runnable() {
            public void run() {
                while (true) {
                    try {
                        consume(productionBelt.take());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            private void consume(String item) {
                System.out.println("Consumed: " + item);
            }
        };

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.execute(producer);
        executorService.execute(consumer);
    }
}
```

Gruß Tom


----------

