# Frage zu Threads & Server



## coffeecups (5. Jan 2014)

Hallo,

hab wegen des Problems bereits einen Thread offen, aber ich denke mit dem FAQ Beitrag von euch lässt es sich besser erklären:

 Netzwerkgrundlagen - ServerSocket und Socket 

Ausgangspunkt ist also das anschauliche Beispiel bei 4. Threads und Server:

(Copy+Paste)
Server

```
[...]
    // Server aufbauen
    ServerSocket server = new ServerSocket(1234);
    Socket s;
    while(true) {
    // Auf verbindung warten
    s = server.accept();
    // kommunikation an einen nebenläufigen Thread abgeben
    ServerThread t = new ServerThread(s);
    t.start();
    // und wieder auf neue Verbindungen warten
    }
```

ServerThread:

```
public class ServerThread extends Thread {
    private Socket s;
    public ServerThread(Socket s) {
    this.s = s;
    }
     
    public void run() {
    // lesen
    BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
    String text = in.readLine();
    // schreiben
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
    out.write(text.toUpperCase());
    out.newLine();
    out.flush();
    // aufräumen
    out.close();
    in.close();
    }
    }
```

Es geht mir darum, wenn mein Server gerade beschäftigt ist (z.B. durch einen einfachen Thread.sleep(5000)), funktioniert die parallele Threadabarbeitung nicht mehr. Grund dafür scheint der BufferedReader/InputStreamReader zu sein. Siehe dazu das folgende Beispiel (Ausgangspunkt der Sourcecode von oben):

ServerTest.java:

```
package servertest;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(1234);
        Socket s;
        while (true) {
            s = server.accept();
            ServerThread t = new ServerThread(s);
            t.start();
        }
    }
}
```

ServerThread.java:

```
package servertest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ServerThread extends Thread {

    private Socket s;
    public ServerThread(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
  
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String text = in.readLine();
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
            
            System.out.println("Sleepy");
            Thread.sleep(8000);
            out.write(text.toUpperCase());
            out.newLine();
            out.flush();
            out.close();
            in.close();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
```

Ich hab hier einfach nur zwei Zeilen hinzugefügt:
            System.out.println("Sleepy");
            Thread.sleep(8000);

Versuche ich jetzt mit 2 Threads gleichzeitig auf localhost:1234 zuzugreifen, dann wird die Anfrage nacheinander durchgeführt, d.h. erst nach 8 vollen Sekunden beginnt der Thread mit der zweiten Abarbeitung obwohl beide Anfragen fast gleichzeitig durchgeführt wurden.

Woran liegt das und vor allen Dingen: wie kann ich das umgehen?

In weiterer Folge geht es mir darum: ich hab einen Java Server der mir Daten aufbereitet. Während dieser Datenaufbereitung ist der Server busy und alle weiteren Anfragen sollen über diesen Zustand informiert werden. Derzeit werden einfach alle Anfragen "gestaut" und ich weiß nicht, wie ich damit umgehen kann/soll.


----------



## ChristianK (5. Jan 2014)

Idealerweise hast du eine Klasse, die nur Verbindungen annimmt. Dann eine Klasse, die als eigenständiger Thread agiert. Wenn dieser Thread schläft, können weiterhin neue Verbindungen aufgenommen werden oder mit anderen Verbindungen gearbeitet werden. Wichtig ist, das jede Verbindung in einem eigenen Thread ist.

Wenn du nun im Haupt-Thread - der die Verbindungen annimmt und die anderen Threads erzeugt -, eine Liste mit allen aktiven Clients führst, kannst du von den Verbindungs-Threads an alle Verbindungen eine Nachricht senden (statische Methode, durch alle iterieren und senden, ...).


----------



## coffeecups (5. Jan 2014)

Sorry habs noch nicht ganz überrissen, kannst dus bisschen genauer erklären wie das Ganze aufgebaut sein soll damit Inputstream nicht weiter blockiert, idealerweise mit Bsp?

Danke & LG


----------



## ChristianK (5. Jan 2014)

[Java]
public SocketServer {
   private ArrayList<Socket> activeSockets = new ArrayList()<>;
   public void run() {
        // init & co ist schon ok
       SocketServer socketServer;
       while(true) {
            Socket socket = socketServer.accept();
            ServerThread thread = new ServerThread(socket);
            activeSockets.add(thread);
            thread.start();
       }
    }
}
public ServerThread extends Thread {
   private Socket socket;
   public ServerThread(Socket socket) { this.socket = socket; }
   public void run() throws IOException {
        try (
           BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream());
           BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream());
       ) {
          String line;
          while (true) {
                line = in.readLine();
                if (line == null) { throw IOException("connection lost"); }
                // arbeite hier mit den informationen
          }
       } catch (IOException e) { throw e; }
   }
}[/code]

So ungefähr. Da hat jede Verbindung ihren eigenen Thread und kann unabhängig von anderen Verbindungen agieren. Verstehe ich richtig, dass das etwa das war, was du wolltest?


----------



## Sen-Mithrarin (6. Jan 2014)

@TO
ähm ... was genau meinst du jetzt ?

"Es geht mir darum, wenn mein Server gerade beschäftigt ist (z.B. durch einen einfachen Thread.sleep(5000)), funktioniert die parallele Threadabarbeitung nicht mehr."

HÄ ? WAT IS ?

was genau meinst du mit "funktioniert die parallel Threadabarbeitung nicht mehr" ???
und was hat das mit deinem code zu tun ?

das was du gepostet hast ist das du genau den einen connection-thread der für die kommunikation mit dem client zuständig ist schlafen legst ... und auch nur diesen
ergo : genau diese verbindung macht erstmal "pause"

alle anderen verbindungen die du offen hast laufen ja in ihren eigenen threads weiter ...
außer : du verwendest die selbe klasse auch für andere connections ... weil dann machen die genau so pause ...

das, was du beschreibst, das zwei clienten pause machen, liegt einfach darin das du das auch so in der klasse geschrieben hast


du brauchst aber gar kein sleep() ... weil read() blockiert, genau wie accept(), und nur dann weiterlaufen wenn was passiert, ansonsten bleibt der thread an dieser stelle eh stehen



entweder hast du irgendwie was mit den grundlagen der parallelen programmierung bzw socket-programmierung nicht verstanden ... oder dich einfach so undeutlich ausgedrückt das nicht klar wird was jetzt eigentlich dein problem ist


----------

