# Timeout setzen



## noch_anfänger (24. Mai 2010)

Hallo,

ich muss Timeout setzen, weiß aber nicht wie... Das Gerät muss versuchen, id zu lesen, wenn es das in 30 Sekunden nicht schafft, muss die Meldung "ID nicht gelesen" ausgegeben werden.

Der Code-Abschnitt, für welchen Timeout gesetzt werden soll:

```
idOne = soapClient.readVariableString("12345");
if (idOne.length() != 14) { // Nicht 'No transponder'
... // Hier wird idOne bearbeitet
...
}
else {
       System.out.println("ID nicht gelesen...");
      }
```


----------



## mabuhay (24. Mai 2010)

Hmmn evtl. eine Schlaufe welche 30 mal ausgeführt wird und jeweils 1s mit sleep(1000) wartet? Du solltest es dann aber in einen eigenen Thread auslagern dass nicht die ganze Applikation geblockt wird (wenn du das nicht schon hast).

mfg


----------



## noch_anfänger (24. Mai 2010)

Innerhalb der if-Schleife gibt es schon drei

```
try {
                Thread.sleep(3000);
		} catch (InterruptedException e) {
		}
```
Und ansonsten noch welche. Ich sollte evtl. andere Threads auch auslagern...

Wie kann man einen Thread auslagern?


----------



## Gast2 (24. Mai 2010)

von welchem typ ist soapClient ?


----------



## andre111 (24. Mai 2010)

If-Schleife


----------



## kay73 (24. Mai 2010)

noch_anfänger hat gesagt.:


> Wie kann man einen Thread auslagern?


Es gibt ab Java 1.5 das 
	
	
	
	





```
util.concurrent
```
 Paket, mit dem 
	
	
	
	





```
Future
```
-Typen, der genau so ein Warte-Feature hat.

Die Sache hat aber einen Riesenhaken: Wenn eine I/O-Operation auf einem alten 
	
	
	
	





```
InputStream
```
 wie 
	
	
	
	





```
System.in
```
 oder einem 
	
	
	
	





```
Socket.read()
```
 blockiert, reicht es nicht, per 
	
	
	
	





```
Future.cancel()
```
 den Thread zu 
	
	
	
	





```
interrupt()
```
-en, sondern der InputStream bzw. Socket muss geschlossen werden, damit der Thread mit einer Exception aussteigt. 

Es ist dringend zu empfehlen, dass Du Deine Netzwerkfuntionen wie unten auf NIO-
	
	
	
	





```
InterruptibleChannel
```
s umstellst, denn deren Blockieren wird korrekt von  unterbrochen.


```
package timeout;

import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class timeoutDemo {

	public static void main(String[] args) {
		try {
			final ExecutorService exs = Executors.newCachedThreadPool();

			final Future<Object> f = exs.submit(new Callable<Object>() {

				@Override
				public Object call() throws Exception {
					final SocketChannel ch = SocketChannel.open(new InetSocketAddress(Inet4Address.getByName("www.google.de"), 80));
					
					// hier passiert gar nichts 
					ch.read(ByteBuffer.allocate(1));
					return null;
				}
			});

			// Keine neuen Jobs mehr entgegennehmen
			exs.shutdown();

			try {
				// Warten, warten, warten
				System.out.println(f.get(30, TimeUnit.SECONDS));
			} catch (final TimeoutException e) {
				
				// Thread abschiessen
				f.cancel(true);
				throw e;
			}
		} catch (final Throwable e) {
			e.printStackTrace();
		}
	}
}
```


----------



## noch_anfänger (25. Mai 2010)

Danke für die Antworten!

Ich habe keine Sockets. Ich muss nur die Meldung ausgeben, wenn nach 30 sekunden kein id gelesen wird. Mit dem InterruptibleChannel bin ich überfordert... Ist das nur die einzige Variante, um Threads auszulagern????:L


----------



## mabuhay (26. Mai 2010)

Die Lösung von kay73 scheint was mit Netzwerk zu tun haben, bei dir ist es aber irgend ein an den PC angeschlossenes Gerät nehme ich mal an.

Also du kannst eigene Threads erstellen, welche dann unabhängig vom Haupt-Thread (wo du deine Gui-Aktionen verarbeitest etc., oder einfach alles das nicht blockiert) laufen. Der Haupt-Thread ist derjenige der sozusagen mit der main-Methode gestartet wird.

Ein Thread sieht grob so aus, wobei es eigentlich ein ganz normales Objekt ist wo du die run()-Methode überschreibst und mit deinem Code füllst:

```
public class SomeThreadObject extends Thread {

	private boolean done = false;  //evtl. volatile?
	private boolean doneOK = false;

	public SomeThreadObject() {

	}

	@Override
	public void run() {

		done = false;
		doneOK = false;

		while (!done) {
			//Hier läuft dann dein Versuch die ID zu lesen etc.
                       sleep(3000);
		}

		doneOK = true;

	}

	public void done() {

		if (!this.isAlive()) {
			return;
		}

		//Wait until the "run"-loop ended
		while (!doneOK) {
			done = true;
			interrupt();

			try {
				sleep(200);
			} catch (InterruptedException e) {}
		}
	}


}
```

Informiere dich doch ein wenig über Threads in Java, ist eine praktische Sache und wirst du in solchen Situationen immer wieder brauchen können.

Hinweis:
1. Anstatt Thread kannst du auch Runnable verwenden. Weiss jetzt nicht mehr genau was die Vorteile sind oder ob es überhaupt Vorteile gibt.
2. Wenn sich der Thread nicht sowieso selbst beendet (wenn die run-Methode fertig ist) brauchst du die done() Methode nicht. Willst du den Thread aber "von aussen" beenden, musst du selbst einen Mechanismus einbauen, zum Beispiel wie ich es im Codebeispiel habe.

mfg


----------



## kay73 (27. Mai 2010)

mabuhay hat gesagt.:


> Die Lösung von kay73 scheint was mit Netzwerk zu tun haben, bei dir ist es aber irgend ein an den PC angeschlossenes Gerät nehme ich mal an.


 Da stand was von SOAP-Client. Aber egal, meine Aussage bezieht sich generell auf das Blockieren von Leseoperation. Du bist dabei, den Thread-Ersteller in genau die Fallen hinein zu manoevrieren, von denen ich spreche.

Ausserdem:

Du versuchst, das Rad neu zu erfinden. Das concurrent-Paket waere auch was fuer Dich. 



mabuhay hat gesagt.:


> 1. Anstatt Thread kannst du auch Runnable verwenden. Weiss jetzt nicht mehr genau was die Vorteile sind oder ob es überhaupt Vorteile gibt.


Es macht im Allgemeinen keinerlei Sinn, eine Klasse von 
	
	
	
	





```
Thread
```
 abzuleiten. 
Keines der Probleme des Probleme des Thread-Erstellers wird angesprochen.
Ersetz' mal Dein 
	
	
	
	





```
sleep(3000);
```
 gegen 
	
	
	
	





```
System.in.read()
```
 und versuch mal den Thread per 
	
	
	
	





```
interrupt()
```
 zu beenden.


----------



## noch_anfänger (27. Mai 2010)

Hier noch mal kurz der Code-Abschnitt, um deutlicher zu machen, was ich habe:


```
public class Task extends TimerTask {
...
...
public void run() {
idOne = soapClient.readVariableString("12345"); // Hier wird id gelesen. In der Variable idOne 
//bekommt man entweder id oder "No Transponder". Wenn nach 30 Sekunden nur "No Transponder"
//kommt, muss die Meldung ausgegeben werden (ein output einschalten).
// Dafür will Timeout!
if (idOne.length() != 14) { // Nicht 'No transponder'
 // Weiter wird idOne bearbeitet
try {
			ResultSet rs = null;
			rs = Database.getInstance().getDatabaseResponse(
				"\"" + idOne.substring(6, 30) + "\"");

			if (rs.next()) {
			    writeFunktion(rs);
			    
			    /**
			     * output1 auf grün setzen
			     */
			    soapClient.writeVariableBoolean("34808", true); 
			    soapClient.executeScript("12970"); 
                           /**
			     * output1 (grün) ausschalten nach 3 Sekunden
			     */
			    try {
				Thread.sleep(3000);
			    } catch (InterruptedException e) {
			    }
			    soapClient.writeVariableBoolean("34808", false); 
			    soapClient.executeScript("12970");
                            ...
                            ...
                            ...
                            ...  // Hier kommt noch etwas
} catch (SQLException e) {
			e.printStackTrace();
		    } 
} else {
       System.out.println("ID nicht gelesen...");
      }
      ...
      ...
      ... // Hier kommt noch etwas
}
}
```

In Main wird die Klasse aufgerufen:

```
public Main() {
        Database.getInstance().connectDatabase(...);
        ...
        ...
        final Timer timer = new Timer();
	timer.schedule(new Task(), 2000, 20000);
        JFrame displayFrame = new JFrame("...");
        ...
        ...
        displayFrame.addWindowListener(new WindowAdapter() {

	    public void windowClosing(WindowEvent e) {
		System.out.println("Closing database connection ...");
		timer.cancel();
		Database.getInstance().closeConnection();
		System.exit(0);
	    }
	});
}
```

Kann ich in der Klasse Task ein Timeout setzen oder Threads auslagern?


----------



## mabuhay (27. Mai 2010)

kay73 hat gesagt.:


> Da stand was von SOAP-Client. Aber egal, meine Aussage bezieht sich generell auf das Blockieren von Leseoperation. Du bist dabei, den Thread-Ersteller in genau die Fallen hinein zu manoevrieren, von denen ich spreche.
> 
> Ausserdem:
> 
> ...


Ja stimmt, bin ein wenig Abgewichen, eigentlich gings ja nur um die Möglichkeit des Timeouts... Werde mir das concurrent-Paket auf jeden Fall auch mal Anschauen. Das unterbrechen während read() ist mit meiner Methode natürlich nicht möglich. Ich habs halt auch schon mit Pollen versucht, also dass zum Beispiel jede Sekunde versucht wird zu lesen oder eine Verbindung aufzubauen. Ist aber natürlich nicht so schön...

Wieso genau macht es keinen "Sinn", eine Klasse von Thread abzuleiten? Wenn ich einen Thread habe der zum Beispiel etwas berechnet, sollte ich dann auch das concurrent-Paket verwenden oder ist dann Runnable/Thread angebracht? Bin bis jetzt bei der Suche nach Thread-Lösungen leider noch nie über das concurrent-Paket gestossen. Btw, in diesem Tutorial Defining and Starting a Thread (The Java™ Tutorials > Essential Classes > Concurrency) wird aber auch Runnable/Thread Beschrieben. Sowie ich das aber verstehe ist Runnable/Thread ok für Simple Anwendungen, für Komplexere Anwendungen und zur Ausnützung aller Features sollte aber java.util.concurrent verwendet werden (High Level Concurrency Objects (The Java™ Tutorials > Essential Classes > Concurrency)) ...sorry für die Abschweifung und Danke für den Hinweis 

mfg


----------

