Verständnisfrage zu Threads: Reihenfolge und BufferedOutputStream

  • Antworten:6
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 41

17.10.2016 19:28:53 via Website

Angenommen, folgender Code:

public void SendFileThread(final int threadID, final String path){
AsynchUtil.runAsynchronously(new Runnable() {@Override
public void run() {
final File file = new File(path);
byte[] bytes = new byte[(int) file.length()];
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bis.read(bytes, 0, bytes.length);
bos.write(bytes, 0, bytes.length);
bos.flush();
ThreadFinish(threadID);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
});
}

Was würde nun passieren, wenn ich diese Methode vom GUI-thread aus mehrmals ausführe, mit verschiedenen Parametern? Würde der zweite Thread erst nach dem Ende des ersten beginnen zu laufen, oder laufen beide gleichzeitig?

Um das zu testen, habe ich eine App geschrieben, die bei Button-Klick diese Methode gleich zwei mal ausführt, allerdings mit zwei unterschiedlichen File-Pfad-Parametern. Die erste Datei ist eine Textdatei voller "AAAAAAA...", die zweite voller "BBBBBBBB...".

Betätigt man diesen Button, kommen auf dem Server zuerst nur die AAAAA-Dateien an. Erst wenn das letzte A angekommen ist, kommen die ganzen Bs.

Daraus KÖNNTE man schließen, dass die Threads sequentiell und nicht simultan ausgeführt werden.

Allerdings bin ich dem nicht so ganz sicher. Es könnte ja auch sein, dass der Buffer vom BufferedOutputStreams (oder vom Socket-Output-Stream??!) dafür sorgt, dass nicht mehrere threads ihn gleichzeitig füllen können, d.h., Datei "B" kommt erst rein, wenn der Datei "A" fertig eingelesen wird.
Falls ich damit recht haben sollte.... was passiert mit einem Thread (hier Thread2 mit B-Datei), wenn sein Einschreibungsvorgang in den Buffer (oder Socketstream oder was auch immer) aus den o.g. Gründen blockiert wird? Wird der ganze Thread blockiert, oder läuft er weiter? Beim letzteren könnte man sich die "Streamabteilung" ja wie ein eigener Thread vorstellen.

Würde mich hier über etwas Aufklärung von einem Experten sehr freuen.

Vielen Dank

  • Forum-Beiträge: 2.214

17.10.2016 20:55:37 via Website

Hallo Arne,

Daraus KÖNNTE man schließen, dass die Threads sequentiell und nicht simultan ausgeführt werden.

Das ist richtg !

Lt. meiner Info verhält sich AsyncUtil äquivalent zu AsyncTask.
Es sei denn , du startest den Task mit AsyncTask.THREAD_POOL_EXECUTOR
Beides ist nur ein Workaround um einen nakten Thread, um dem Entwickler die Implementation zu erleichtern

Aber diese Mimik ist ja eh falsch für dich (longlife) , mit AsyncUtil hast du dir praktisch ein AsyncTask wieder ins Haus geholt.

Wir hatten schon mal den Punkt in einen deiner vorherigen Beiträgen angesprochen .
https://www.androidpit.de/forum/724049/warum-funktioniert-meine-simple-app-nicht-android-studio

Schau mal hier , da hatte ich ein ähnliches Problem und die Lösung steht ganz zum Schluss.
https://www.androidpit.de/forum/720637/verstaendniss-problem-asynctask-s
.

Für Longlife musst aber in diese Richtung .....
https://developer.android.com/training/multiple-threads/define-runnable.html
.

P.S. Ein Socket arbeitet serial nach FIFO.
Mit zwei Threads auf ein und den selben Socket zuzugreiffen ist somit tödlich.
Ich würde EINEN Thread bauen , der sequentiel ein internes FIFO Array abarbeitet.
Für die Zuordnung vergibst du Message-ID-Tags (je nach Handshake)

— geändert am 18.10.2016 09:28:32

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 41

22.10.2016 05:18:27 via Website

Hey Stefan,

danke nochmal. Ich meine ziemlich gut verstanden zu haben, was du geschrieben hast.

Also ich schreibe quasi eine Chat-App, mit der man auch Dateien senden kann (nur eine Verbindung, also 1 Socket).

Wenn ich es gut machen möchte, sollte ich hierfür mindestens 2 Threads neben dem UI-Thread verwenden, die parallel laufen können sollten, da ein Thread ja quasi permanent darauf achten muss, ob gerade eine Nachricht reinkommt oder nicht, während der andere sich um rausgehende Nachrichten kümmert. Ohne die Parallelität würde der Thread, der die einkommenden Nachrichten permanent bearbeitet, den Thread für die ausgehenden Nachrichten stets blockieren. richtig soweit?

Für eine kurzfristige Lösung habe ich gerade die folgende Idee: Der Thread für den Empfang schaut nur alle 3 Sekunden nach, ob was neues da ist, d.h. er geht regelmäßig in einen sleep für 3 Sekunden. Dann müsste ja der nächste Thread in der Queue bearbeitet werden, sprich dann könnte der sendende Thread weiterarbeiten, bis dieser fertig ist (da dieser keinen sleep hat) und unmittelbar nach dem ausführen des sende-Threads würde der Empfangsthread wieder zum Zuge kommen. richtig? Dass dann unter umständen dieser erst viel später als 3 Sekunden wieder daran käme, wäre für mich kein Problem. Könnte ich das so machen?
Thread.sleep() geht ja nicht, da es hier ja um AsyncUtil, also eine andere Klasse handelt, oder?

  • Forum-Beiträge: 2.214

22.10.2016 09:18:30 via Website

Guten Morgen Arne,

fast, aber nicht ganz richtig :-)

In der Servertechnik geht man i.d.R hin und baut nur einen Main-Thread für eine Socketverbindung für Beides.
Bevor ich hier lange beschreibe - schau dir folgendes Beispiel an
http://android-er.blogspot.de/2014/08/implement-simple-android-chat.html

Hier kannst du dir die Technik von class ConnectThread extends Thread anschauen.
Den ServerThread benötigst du nicht , denn dieser macht ein listen und accept

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 41

23.10.2016 08:49:28 via Website

Hey Stefan,

danke. Ja, auf diese Seite bin ich auch gestoßen. So ähnlich werde ich meine App auch schreiben. Nur, dass meine App auch Dateien schicken und empfangen soll. Das schicken klappt schon ganz gut. Das Empfangen werde ich auch noch heute oder morgen fertig bekommen.

Wo ich mir noch nicht ganz sicher bin ist, wo ich welche Streamklassen verwenden soll. Es scheinen ja einige zur Auswahl zu stehen:

DataInputStream, Printstream, BufferedInputStream, ByteArrayInputStream

wobei wahrscheinlich alle Unterklassen von InputStream sind. Und dann gibt es die jeweiligen Streams ja auchnochmal als Ausgangsvariante.

Kannst du mir vielleicht sagen, welche Streams wofür geeignet sind? Habe gehört, dass Print einfacher wäre für Strings und Buffered schneller ist, da er wegen dem Puffer mehr Daten auf einmal "schaufeln" kann.

Wichtig wäre das Senden/Empfangen von Strings und Dateidaten. Einzelne char, int, long, float, double Datensätze wären wahrscheinlich auch gut.

  • Forum-Beiträge: 2.214

23.10.2016 09:19:27 via Website

Hallo Arne,

wenn du das Grundgerüst so aufgebaut hast , wie im oberen Link beschrieben , kannst du mit diesem alles erschlagen.

Filetransfer :
I.d.R geht man bei langen Processen hin und lagert diese in Background-Services aus .

— geändert am 23.10.2016 09:48:28

Liebe Grüße - Stefan
[ App - Entwicklung ]

  • Forum-Beiträge: 41

23.10.2016 20:53:19 via Website

Danke, werde ich machen. Wenn es Probleme geben sollte, wirst du wieder von mir hören. Kannst du mir noch ein paar Worte zu den Streamklassen mitgeben?