# RMI Callback (mit Threads?)



## pyramid (16. Dez 2009)

Hallo zusammen

Ich habe ein vermutlich einfaches Problem, das ich nicht zu lösen weiss . Bin totaler Java-Anfänger, deshalb: habt bitte erbarmen .

Folgende Klassenstruktur habe ich:

- Server (startet RMI-Registry)
- Hello (Interface)
- HelloImpl (ArrayList von Clients, Methoden: addClient, removeClient, sendHello)
- Client (Interface)
- ClientImpl(Methoden: getName (über Kommandozeile wird Name übergeben), printHello)
- Main-Klasse mit main-Methode macht folgendes:
-> Referenz auf Hello-Objekt mit Naming.Lookup
-> neuer Client erstellen
-> Client hinzufügen (addClient)
-> warten auf User-input 'end' mit Scanner
-> wenn 'end' dann, Client aus Array-List in Hello entfernen

Der Server soll nun an alle angemeldeten Clients alle zwei Sekunden ein 'Hello World' senden. Die Clients sollen warten, bis der User mit "end" das Programm abbricht und sich dann vom Server wieder abmelden. 

Das sendHello in HelloImpl wird in einer Endlos-Schleife an alle im Array-List gespeicherten Clients geschickt (printHello), danach wird zwei Sekunden geschlafen (sleep(2000).

Nun wird im Client auf den User-Input gewartet. Sobald ich 'end' eingebe, kommt er zwar zur Stelle, wo der Client wieder aus der Array-List entfernt wird, aber der Server schickt trotzdem das Hello World weiter an die Clients. 

Wie unterbreche ich nun meine Endlosschleife in HelloImpl.sendHello? Muss das sendHello mit einem Thread mit Hilfe von wait und notify realisiert werden? Oder wie kann ich sonst auf den Client umschalten, so dass dort das removeClient ausgeführt werden kann und danach im sendHello der abgemeldete Client keine Hello Worlds mehr erhält?

Ich bin wirklich dankbar für einen Hinweis. Das mit dem RMI-Callback glaube ich verstanden zu haben, aber ob und wie RMI mit allfälligen Threads arbeitet kapier ich nicht.

Vielen Dank für alle Tips im Voraus.

pyramid


----------



## tuxedo (17. Dez 2009)

pyramid hat gesagt.:


> Wie unterbreche ich nun meine Endlosschleife in HelloImpl.sendHello?



Mit einer passenden Abbruch-Bedingung 

```
....

while(!stopped) {

...

}

....

public void stopIt() {
    stopped=true;
}
```

Alles in allem: Der Konstrukt ist etwas "wirr" um es ohne Sourcecode zu erklären. Wie wär's wenn du hier und da dein Vorgehen mit einem Code-Ausschnitt erklärst?

Alex


----------



## pyramid (17. Dez 2009)

Hallo Alex

Vielen Dank für deine Antwort. Das hatte ich auch schon versucht (stopIt hab ich dann im try-Block vor dem Remove aufgerufen in der Main-Klasse und stopped auf true gesetzt), aber hab dann dasselbe Problem, wie ohne: Er ignoriert das dann im HelloImpl in der Endlosschleife komplett, da er irgendwie nicht mehr auf den Main-Thread umschaltet.

Aber du hast recht, ich muss Code posten:


```
public class HelloImpl extends UnicastRemoteObject implements Hello
{
    private ArrayList<Client> Clients;
     public HelloImpl () throws RemoteException
	{
		Clients = new ArrayList<Client>();
	}

       ...
       public synchronized boolean addClient(Client c) throws RemoteException
       {
              ....
              Clients.add(c);
               sendHello();
              ...
        } 
        public synchronized void sendHello() throws RemoteException
	{
		
			while(true)
			{
				for(Iterator<Client> iter = Clients.iterator();iter.hasNext();)
				{
					sleep(2000);
					Client c = iter.next();					
					try
					{
						c.print("Hello World");
					}
					catch(RemoteException e)
					{
						iter.remove();
					}
				}
			}
		}	
                public synchronized void removeClient.....{}
                ....
}

public class Main
{
        public static void main (String[] args)
        {  
             ...
            Hello hello = (Hello)Naming.lookup(path);
            ClientImpl client = new ClientImpl("Name");
            try
            {
                if(hello.addClient(client)
                {
                    Scanner scan = new Scanner(System.in);
                    if(scan.nextLine().equals(""))
                    {
                         hello.removeClient(client);
                    }
                   }
            }
            ....
            }
}
```

So und wenn ich nun den Server gestartet habe, und danach das Main starte, dann kommt er bis zum if(scan.nextLine().equals("")) und danach kann ich solange enter drücken, er kommt dann nicht zum removeClient sondern schickt mir weiterhin hello worlds aus dem HelloImpl auf die Console.

Falls ihr noch mehr Code braucht, gebt einfach Bescheid. 

vg
pyramid


----------



## Ice-Tea (17. Dez 2009)

Zeile 21 schreit ganz laut: "Solange du mich hier nicht raus lässt häng ich mich auf"


----------

