# SerialPort auslesen und Daten verarbeiten



## richiking (27. Dez 2011)

Hallo,

ich arbeite derzeit an einem Projekt bei dem über Bluetooth Daten gesendet werden. Ich lese die virtuelle serielle Schnittstelle aus und will die Daten verarbeiten.
Die Daten kommen dabei immer wiefolgt an: [85, -1, 24,x0,x2,x3...x23]

Wobei die ersten 3 Stellen immer einem Header entsprechen den ich nicht weiter benötige...

Ich suche also nach den 3 Stellen in meinem SerialRingBuffer (siehe Code) und merke mir wo sie stehen... lese dann die Daten aus und lösche den Buffer bis hin zum neuen Header....

Sprich: nach dem ersten Durchlauf sollte i immer 0 bleiben, da ich ja den Buffer genau so lösche dass der Header wieder an stelle 0 steht...

Mein problem... das funktioniert auch hin und wieder... nur fängt er dann an, den header bei 26 oder 50 oder sonst irgendwo zu finden. Die Daten die von Bluetooth her kommen sind als korrekt anzusehen, da ichs mit dem Hyperterminal probiert habe und dort funktioniert....

Hier mal Code:


```
InputStream in;
        SerialPort sport;
    	static boolean headerfound= false;
    	
    	
    	byte[] buffer = new byte[4000];
    	
    	ArrayList fin = new ArrayList();
    	byte[] realdata = new byte[24];



    	byte[] header = {85,-1,24};
    	String out="";
    	StringBuffer serialRingBuffer = new StringBuffer();

    	
        public ComRW ( InputStream in, SerialPort sp )
        {
            this.in = in;
            this.sport=sp;
        }
        
        private void parsedata()
        {

    			try {
    				in.read(buffer);
    				serialRingBuffer.append(new String(buffer).trim());
    				
    				
				} catch (IOException e) {

					e.printStackTrace();
				}
    			
    			
					


    			int i=0;

    			
    			while(!headerfound && serialRingBuffer.length()>=3 && i<serialRingBuffer.length())
    			{
    				
    				if(serialRingBuffer.toString().getBytes()[i]==header[0]&&serialRingBuffer.toString().getBytes()[i+1]==header[1]&&serialRingBuffer.toString().getBytes()[i+2]==header[2])
    				{
    					System.out.println("Header beginnt bei: "+i+"\r\n"); 
    					headerfound=true;
    				}
    				i++;
    				
    			}
    			i--;
    			String outtemp="";		
    			if(i+26<serialRingBuffer.length()&&headerfound)
    			{
    				
    				for(int s=0;s<24;s++)
    				{    						
    					realdata[s]=serialRingBuffer.toString().getBytes()[i+s+3];
    					outtemp = outtemp+realdata[s]+", ";

    				}
    				out = out+outtemp+", ";
    				fin.add(realdata);
    				System.out.println(outtemp);
    				

    				serialRingBuffer.delete(0, i+27);

    			}
    			
    			else if(!headerfound)
    			{
    				serialRingBuffer.delete(0, serialRingBuffer.length()+1);

    			}

    	    	headerfound=false;

	
    		}
```

Und hier noch der Thread-Sleep...


```
public void run ()
        {
 
                while (true)
                {
                		
                		parsedata();
                		try{
                			Thread.sleep(5);
                		}
                		catch (Exception e) {
					// TODO Auto-generated catch block
                			e.printStackTrace();
                		}
                		
}
```

Bitte um Hilfe, ärgere mich schon seit Tagen damit herum. Falls noch zusätzliche Infos benötigt werden bitte Bescheid sagen!

lg, richi


----------



## tagedieb (27. Dez 2011)

Auf ein Schuss ins Blaue würd ich sagen es liegt am StringBuffer!!

Ein String sind encodete Bytes. Das heisst je nach Encoding werden die Bytes umgewandelt und dementsprechend wird auch deine Suche ein falsches ergebnis zurueckliefert. 

Du darfst keine Stringumwandlung verwenden, da deine Daten (zumindest der Header) kein String ist.
Du sollest ein Byte Array oder den ByteBuffer aus dem java.nio Package.


----------



## richiking (28. Dez 2011)

Das komische ist ja nur, dass es größtenteils funktioniert aber dann auf einmal bei stelle 11 im array scheinbar der header auftritt anstatt an stelle 0.... es scheint also als würden sich die 26 byte (od. 27 weiß grad nicht genau) verschieben bzw. als würde ich falsch abschneiden... was ich allerdings schon mehrmals geprüft hätte...


----------



## richiking (28. Dez 2011)

Problem ist ja auch noch, dass der ByteBuffer eine fixe Größe hat oder täusch ich mich?

Ich weiß aber nicht wieviele Daten (hängt von der Laufzeit ab) produziert werden...


----------



## tagedieb (28. Dez 2011)

Du darfst mir schon glauben wenn ich sage *char*s (16 bit) sind keine *byte*s (8 bit). Bei der Umwandlung von bytes in einen String spielt auch das Encoding (UTF-8, ISO0-8859-1) eine Rolle. Da werden bytes geaender, eingefuegt oder rausgeloescht (siehe Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)).

Der ByteBuffer hat eine limitierte Groesse. Du darfst eben nur soviele bytes lesen wie du auch in den Buffer schreiben kannst. Wenn du einen Record verarbeitet hast rufst du buffer.compact() ByteBuffer (Java 2 Platform SE 5.0) auf, damit werden die verarbeiteten Bytes geloescht und es hat wieder Platz fuer neue Daten.

Du brauchst den ByteBuffer ja nicht verwenden wenn du nicht will, aber eine Umwandlung in einen String ist definitiv falsch!


----------



## richiking (29. Dez 2011)

Das glaub ich dir auch, ich finde es nur seltsam dass es, wenn ichs im Debugger ausführe (fast) zu 100% funktioniert, nur wenn ichs normal laufen lasse eben nicht.

Du scheinst ja eine Idee zu haben wie ich das ändern kann. Kannst du mir vl. ein paar Codefetzen als anhaltspunkt geben, da ich nun doch schon ziemlich am verzweifeln bin.

lg, richi


----------



## tagedieb (30. Dez 2011)

Du hast da uebrigens noch einen logischen Fehler im Code. In der *parsedata *Methode liest du bis zu 4000 Bytes ein (Buffergroesse), aber du parst maximal 1 Datensatz. In den 4000 Bytes koennen natuerlich mehrere Datensaetze vorkommen, aber es wird nur 1 Datensatz geparst. Oder aus dem Inputstream werden auch nicht komplette Datensaetze ausgelesen und in den Buffer geschrieben. Da du jedes mal wieder den Buffer ueberschreibst und nicht die restlichen Daten zusammenfuegst gehen diese Daten verloren.

Am einfachsten ist dir wohl geholfen, wenn du einen BufferdInputStream verwendest und keinen eigenen Buffer verwendest. Du liest dann die Bytes direkt aus dem Stream (blockiert aber, wenn du mehr Zeichen ausliest als im Stream verfuegbar sind)

Ich habe mal ein Beispiel mit java.nio und ByteBuffer (non Blocking) gemacht.


```
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class RecordReader {
	private ReadableByteChannel in;
	private ByteBuffer buffer = ByteBuffer.allocate(8192);
	private byte[] header = { 85, -1, 24 };
	List<byte[]> fin = new ArrayList<byte[]>();

	public RecordReader(InputStream is) {
		in = Channels.newChannel(is);
	}

	public void parsedata() {

		byte[] realdata = new byte[24];
		byte[] currentHeader = new byte[3];

		try {
			while (true) {
				in.read(buffer);
				buffer.flip();
				while (buffer.hasRemaining()
						&& buffer.remaining() >= (header.length + realdata.length)) {
					buffer.mark();
					byte b = buffer.get();
					if (b == header[0]) {
						buffer.reset();
						buffer.get(currentHeader);
						if (Arrays.equals(header, currentHeader)) {
							buffer.get(realdata);
							System.out.println(new String(realdata));
							fin.add(realdata);
						} else {
							buffer.reset();
							buffer.get();
						}
					}
				}
				buffer.compact();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		byte[] testdata = { 85, -1, 24, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
				65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 65, 66, 67, 68, 69, 70,
				71, 72, 73, 74, 85, -1, 24, 65, 66, 67, 68, 69, 70, 71, 72, 73,
				74, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 65, 66, 67, 68, 69,
				70, 71, 72, 73, 74, 85, -1, 24, 65, 66, 67, 68, 69, 70, 71, 72,
				73, 74, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 65, 66, 67, 68,
				69, 70, 71, 72, 73, 74, 85, -1, 24, 65, 66, 67, 68, 69, 70, 71,
				72, 73, 74, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 65, 66, 67,
				68, 69, 70, 71, 72, 73, 74, 85, -1, 24, 65, 66, 67, 68, 69, 70,
				71, 72, 73, 74, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 65, 66,
				67, 68, 69, 70, 71, 72, 73, 74, 85, 85, -1, 24, 65, 66, 67, 68,
				69, 70, 71, 72, 73, 74, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
				65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 85 };

		ByteArrayInputStream bais = new ByteArrayInputStream(testdata);
		new RecordReader(bais).parsedata();
	}
}
```


----------



## richiking (30. Dez 2011)

Vielen lieben Dank! 
Das sieht sehr vielversprechend aus. Ich verstehe zwar noch nicht alle Methoden/Befehle die du verwendest aber das werd ich mir schon noch genauer anschauen.... das einzige Problem dass ich jetzt noch habe ist, dass die Ausgabe in der Konsole jetzt natürlich in ASCII-Format erfolgt. Ich will allerdings ganz gerne die repräsentativen Zahlenwerte sehen (wie in deinen Testdaten)... Hab schon ein paar Sachen durchprobiert aber bin noch auf keinen grünen Zweig gekommen. Vielleicht hast du da ja noch eine Idee, wäre toll...


lg, richi


PS: Hat sich erledigt danke...


----------



## richiking (30. Dez 2011)

Ok, es sieht jetzt folgendermaßen aus...

Aufgerufen wird das ganze so:


```
l = new Thread(new forum(vc_l.getinstream()));
		        l.start();
```

Und der Einlese-Code:


```
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
public class forum implements Runnable {
    private ReadableByteChannel in;
    private ByteBuffer buffer = ByteBuffer.allocate(8192);
    private byte[] header = { 85, -1, 24 };
    List<byte[]> fin = new ArrayList<byte[]>();

 
    public forum(InputStream is) {
        in = Channels.newChannel(is);
    }
 
    public void parsedata() {
 
        byte[] realdata = new byte[24];
        byte[] currentHeader = new byte[3];
 
        try {
            while (true) {
                in.read(buffer);
                buffer.flip();
                while (buffer.hasRemaining()
                        && buffer.remaining() >= (header.length + realdata.length)) {
                    buffer.mark();
                    byte b = buffer.get();
                    if (b == header[0]) {
                        buffer.reset();
                        buffer.get(currentHeader);
                        if (Arrays.equals(header, currentHeader)) 
                        {
                            buffer.get(realdata);  
                            System.out.println(Arrays.toString(realdata));
                            fin.add(realdata);
                            
                        } 
                        else 
                        {
                            buffer.reset();
                            buffer.get();
                        }
                    }
                }
                buffer.compact();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void run ()
    {

            while (true)
            {
            		
            		parsedata();
            		try{
            			Thread.sleep(5);
            		}
            		catch (Exception e) {
				// TODO Auto-generated catch block
            			e.printStackTrace();
            		}            		            			            
            }
    }
}
```


Die Ausgabe ist folgende:


```
[103, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -4, -1, -52, -1, -19, -1]
[104, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -86, -1, -1, -2, -114, -1]
[104, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 124, 85, -1, 24, 104, 5]
[104, 5, 1, 0, -1, 125, -2, 78, -1, 35, 85, -1, 24, 104, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5]
[104, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 109, -1, -90, -2, 18, -1]
[104, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -29, -1, 72, -1, -55, -1]
[105, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 36, 0, 64, 0, 29, 0]
[106, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -15, -1, -105, -1, -1, 85]
[106, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -28, 85, -1, 24, 107, 5]
[108, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -10, -1, -100, -1, -30, -1]
[109, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, -9, -1, -45, -1, -22, -1]
[109, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 0, 0, -69, -1, -1, 24]
[108, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 85, -22, -1, 85, 85, -1, 24, 110, 5, 1, 0, 2]
[111, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 85, -1, 24, 112, 5, 1, 0, 2, 0, 3, 0]
[111, 5, 1, 0, 2, 0, 3, 0, 0, 7, 0, 8, 0, 9, 0, -42, -1, 1, 0, 38, 0, 85, -1, 24]
[113, 5, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 49, 0, 125, 0, 42, 0]
... (usw...)
...
...
[code=Java]

Wie man sieht, steht der Header in der Ausgabe mit drin, was ja eigentlich nicht sein dürfte.... das Problem hatte ich mit meiner Version auch immer... es scheint sich etwas zu verschieben, oder liegt das wieder am Encoding?! Wie kann ich das dann lösen?

Hoffe ich nerv damit nicht schon, aber es ist ein ziemlich wichtiges Projekt für mich...

Danke schonmal für die großartige Hilfe bis jetzt!
```


----------



## tagedieb (30. Dez 2011)

System.out.println(Arrays.toString(realdata));


----------



## tagedieb (30. Dez 2011)

Bist du sicher, dass alle Records 27 byte lang sind? Eventuell gibt es auch kuerzere Records?

Anonsten wuerd ich mal alles ausgeben was aus dem InputStream kommt und ueberpruefen ob da auch alles so gestreamt wird wie du das erwartest (even fixe Recordlaenge).

Ausserdem musst du aufpassen mit der parsedata Methode. Im moment laeuft die unendlich, ausser es wird eine exception geworfen. Dein 
	
	
	
	





```
Thread.sleep(5);
```
 wird gar nie durchlaufen werden.


----------



## richiking (30. Dez 2011)

Sodala,
hab jetzt folgendes verändert...


```
while(true)
```

zu


```
while (in.read(buffer)>0)
```


habs jetzt mehrere Male ausprobiert und es scheint zu funktionieren. Vielen vielen vielen Dank!!! :applaus:


----------



## richiking (10. Feb 2012)

So nach langem Hin- und Her stehe ich wieder vor einem Problem...

Der ReadablyByteChannel scheint mir zu blockieren falls von der seriellen Schnittstelle nichts mehr ankommt... 

Frage: Kann man dies verhindern?


----------



## tagedieb (10. Feb 2012)

Wie soll man etwas verhindern was nur scheinbar auftritt? 

Hast du ein Beispiel wo du das Problem reproduzieren kannst? Kannst du die letzte Version deines Codes hochladen?


----------



## HoaX (10. Feb 2012)

Wieso sollte er nicht blockieren? Es kann ja wie du sagst doch noch was kommen...


----------



## Spacerat (10. Feb 2012)

Natürlich blockiert er... warum auch nicht, ist normal für Datenempfänger. Zum Beenden eines Empfängerthreads vom Sender aus wird ein "Hang up"-Signal benötigt. Auf der Empfängerseite kann man aber auch mit einem Timeout arbeiten.


----------



## richiking (12. Feb 2012)

Ja es ist mir auch klar dass er blockiert... hab meine frage vielleich blöd gestellt...

aber wie kann ich ihm sagen er soll den thread dann beenden wenn nichts mehr ankommt?


----------



## Spacerat (12. Feb 2012)

Das kann man auf verschiedene Weise regeln, in jedem Fall wird ein weiterer Thread benötigt, welcher den anderen (blockierten) Thread nach einer gewissen Zeit beendet (abwürgen wäre hier eigentlich der bessere Begriff) weil dieser nicht die Zeit seiner letzten Aktivität melden konnte.


----------



## richiking (12. Feb 2012)

Also... der Code entspricht dem zuletzt gepostetem Code... 

Ich habe jetzt folgendes versucht:

Thread A: Daten auslesen (in.read(buffer))....

In der Klasse die der Thread A bedient wird eine boolean Variable true gesetzt nach jedem erfolgreichem einlesen und bleibt false falls in.read() blockiert. Weiters habe ich eine get-Methode für jene Boolean Variable implementiert.

In Thread B rufe ich immer wieder diese Methode auf und überprüfe ob true... falls nicht mache ich ein Thread A.sleep für ein paar millisekunden... und wenn die methode dann wieder false zurückliefert dann stoppe ich den Thread A...

Jetzt habe ich allerdings das Problem, dass Thread A durch dies sehr langsam geworden ist und hinterherhängt...

CODE Thread B:


```
public class Checkport implements Runnable {
	
	Thread th;
	Data vd;
	
	public Checkport(Thread t, Data d)
	{
		th=t;
		vd=d;
	}
	
	public void run()
	{
		while(true)
		{
			if(!vd.checkRunning())
			{
				try {
					th.sleep(10);
					
					if(!vd.checkRunning())
					{
						th.stop();
						System.out.println("Alles Kaputt");
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
			}
			
			else
			{
				System.out.println("OK");
			}
		}
	}
```

CODE Thread A:


```
boolean isrunning = true;

try {
isrunning = false;
            while (in.read(buffer)>0) 
            {
isrunning = true;
            	
                buffer.flip();
               
                while (buffer.hasRemaining()
                        && buffer.remaining() >= (header.length + realdata.length)) {
                    buffer.mark();
                    byte b = buffer.get();
                   
                    if (b == header[0]) 
                    {
                        buffer.reset();                                               
                        buffer.get(currentHeader);
                        
                        if (Arrays.equals(header, currentHeader)) 
                        {
                        	realdata = new byte[size_data];
                            buffer.get(realdata);  
                            System.out.println(Arrays.toString(realdata));       // Print ohne Parsen                     
                            fin.add(realdata);
                            

                             
                        else 
                        {
                            buffer.reset();
                            buffer.get();
                        }
                    }
                }
                buffer.compact();
            }
            

            
        } catch (IOException e) {
            e.printStackTrace();
        }
```


----------



## Spacerat (12. Feb 2012)

Eigentlich ist so ein TimeOut-Thread relativ simpel zu realisieren.

```
public class TimeOutWatchDog
{
	private static final long TIMEOUT = 5000L;

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		ReaderThread r = new ReaderThread();
		TimerThread  t = new TimerThread(r, TIMEOUT);
		r.start();
		t.start();
	}

	private static final class ReaderThread
	extends Thread
	{
		private long lastActivity;
		private boolean running;

		private ReaderThread()
		{
			super("reader");
		}

		@Override
		public synchronized void start()
		{
			running = true;
			super.start();
		}

		@Override
		public boolean isInterrupted()
		{
			return !running;
		}

		@Override
		public void interrupt()
		{
			running = false;
		}

		@Override
		public void run()
		{
			while(!isInterrupted()) {
				// diese Zeit muss bei jedem Durchlauf erneuert werden.
				lastActivity = System.currentTimeMillis();
				synchronized(this) {
					// Simulation des Lesevorganges ganz simpel
					try {
						wait((long) (Math.random() * TIMEOUT * 2) + 10L);
					} catch(InterruptedException e) {
						// interrupt();
					}
				}
			}
			System.out.println("now I'm kicked :(");
		}

		public long getLastActivity()
		{
			return lastActivity;
		}
	}

	private static final class TimerThread
	extends Thread
	{
		private final ReaderThread reader;
		private final long timeOut;

		private TimerThread(ReaderThread source, long timeOut)
		{
			super("timer");
			if(source == null) {
				throw new IllegalArgumentException("source may not be null");
			}
			if(timeOut < 20L) {
				throw new IllegalArgumentException("timeOut may not be smaller than 20");
			}
			this.timeOut = timeOut;
			this.reader = source;
		}

		@Override
		public void interrupt()
		{
			reader.interrupt();
			try {
				reader.join();
			} catch(InterruptedException e) {
				// interrupt();
			}
			super.interrupt();
		}

		@Override
		public void run()
		{
			long lastActivity, currentTime;
			while(!isInterrupted()) {
				synchronized(this) {
					try {
						wait(timeOut / 2);
					} catch(InterruptedException e) {
						// interrupt();
					}
				}
				lastActivity = reader.getLastActivity();
				currentTime = System.currentTimeMillis();
				System.out.println(currentTime - lastActivity);
				if(currentTime - lastActivity > timeOut) {
					interrupt();
				}
			}
			System.out.println("nothing to watch at.");
		}
	}
}
```
Erstens ist es hier wichtig, dass der Lesethread kurz vor dem Timeoutthread (also scheinbar gleichzeitig) gestartet wird, weil letzterer nur eine Timerperiode auf den Lesethread wartet und sich dann beendet. Die Art, wie der Lesethread hier beendet werden soll (durch einen anderen Thread) macht es in vielen Fällen erforderlich (sicherer), dass [c]isInterrupted()[/c], [c]interrupt()[/c] und [c]start()[/c] wie gezeigt überschrieben werden, damit wird im Zweifelsfall ein Deadlock verhindert.


----------



## richiking (12. Feb 2012)

Spacerat hat gesagt.:


> Eigentlich ist so ein TimeOut-Thread relativ simpel zu realisieren.



Das liegt im Auge des Betrachters 

Ich werd morgen versuchen den Code zu verstehen und in mein Projekt einzubauen. 

Danke dir/euch vorerst einmal, melde mich falls es noch Probleme geben sollte...

Danke !


----------



## richiking (18. Feb 2012)

Ok habe es ausprobiert mit Ihrer/deiner Lösung, doch leider gibt mir die Konsole nach Start der beiden Threads augenblicklich "now i'm kicked" aus...

ohne code ws. keine fehlerbehebung möglich right?


----------



## Spacerat (18. Feb 2012)

Wie augenblicklich? Also mein Beispiel ist wirklich nur ein KSKB, welches erst nach 5000 Millisekunden zum ersten Mal die Möglichkeit bekommt, auszusteigen. Das liegt an der TIMEOUT-Konstante.
Der Reader schläft pro Durchlauf in Zeitspannen zwischen 10 und 10000 (2*TIMEOUT) Millisekunden.
Der Timer fragt alle 2500 Millisekunden den Zeitpunkt der letzten Aktivität des Readers ab. Wenn dieser Zeitpunkt TIMEOUT überschreitet, wird der Reader unterbrochen ("now I'm kicked ") und der Timer beendet sich selbst ("nothing to watch at.").
Natürlich muss TIMEOUT und die "run()"-Methode des Readers deinen Ansprüchen nach angepasst werden und dessen Sleep-Time sollte keineswegs, wenn überhaupt eine benötigt wird, zufällig ermittelt werden. Nur das update der "lastActivity" ist wichtig.


----------



## richiking (18. Feb 2012)

Ähm direkt nach Start der beiden Threads...


ABER, egal... ich hab jetzt das vorgeschlagene script etwas erleichtert damit ich es auch versteh und frage jetzt einfach jede sekunde ab ob die lastactivity + der timeout zeit < der aktuellen systemzeit ist...

und das scheint jetzt zu funktionieren... danke!


----------

