Toon posts:

[JAVA] Welke Thread-variant is beter?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

Ik ben bezig met het maken van een java chatbox. En voor de server heb ik nu 1 Thread lopen voor alle clients, de clients worden toegevoegd aan een Hashtable. Maar mijn vraag is nu: Is het aanmaken van een Thread voor elke client apart beter dan de methode die ik nu gebruik en wat zijn de voor- en nadelen van beide manieren.

}:O

  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

Voordelen meerdere threads: Als 1 thread hangt, of wacht, of crasht, of whatever, loopt de rest gewoon door.
Nadelen: 't kost implementatietijd, en je moet controle over al je threads houden. Ook kun je synchronisatieprobleempjes krijgen, moet je oppassen voor deadlocks en dergelijke.

Overigens lijkt dit mij een logisch multi-threaded systeem. Ik snap eigenlijk niet goed hoe je het (handig en logisch) voor elkaar krijgt met meerdere clients te communiceren zonder threads? Hoe ziet je opbouw er nu uit?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:49
Ik weet helaas niet meer precies hoe Java sockets werken, maar er zijn in het algemeen twee oplossingen mogelijk.

Ten eerste kun je elke client een aparte thread geven. Die thread beheert ook de client socket en luistert continue naar binnenkomende berichten (die dan ook naar andere clients gestuurd kunnen worden). Dit werkt op zich prima.

Ten tweede kun je gebruik maken van een select mechanisme, waarbij je met een select call direct kunt zien welke van alle client sockets data beschikbaar hebben. Je hebt dan een enkele thread waarin alle connecties afgehandeld worden. Ik weet niet in hoeverre dit in Java mogelijk is, aangezien er volgens mij niets select-achtigs bestaat.

De grote voordelen van de tweede methode zijn dat je je geen zorgen hoeft te maken over synchronisatieproblemen (aangezien er een enkele thread is) en de oplossing goed te schalen is. Onder de meeste operating systems is het niet de bedoeling dat er een proces uit honderden of duizenden threads bestaat. Als je wel zoveel clients wilt ondersteunen, dan kun je dus beter voor de tweede oplossing kiezen.

Het enige echte voordeel van de eerste oplossing is dat je elke client in een apart object behandeld en dat de code daardoor duidelijk te lezen en makkelijk te schrijven is. Je moet dan echter wel rekeninghouden met het synchroniseren van de gedeelde bronnen.

  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

Soultaker schreef op 18 september 2002 @ 14:48:
Ten tweede kun je gebruik maken van een select mechanisme, waarbij je met een select call direct kunt zien welke van alle client sockets data beschikbaar hebben. Je hebt dan een enkele thread waarin alle connecties afgehandeld worden. Ik weet niet in hoeverre dit in Java mogelijk is, aangezien er volgens mij niets select-achtigs bestaat.
Voor zover ik iets van java weet kan dat niet zomaar... alle I/O is blocking. (Maar ik weet er weinig van, dat is waar).
Kijk ook eens naar: http://www.cs.berkeley.edu/~mdw/proj/java-nbio/

Verwijderd

Heb je in Java geen Threadpools? Als je voor elke client een nieuwe thread moet starten dan geeft dat nogal wat overhead. Bij threadpools worden je threads niet telkens geinstantieerd/vernietigd wat de snelheid ten goede komt. Ik denk dat dit hiervoor een uitstekende oplossing is.

  • Pooh
  • Registratie: April 2001
  • Niet online

Pooh

Lees eens een boek

Verwijderd schreef op 18 september 2002 @ 15:06:
Heb je in Java geen Threadpools? Als je voor elke client een nieuwe thread moet starten dan geeft dat nogal wat overhead. Bij threadpools worden je threads niet telkens geinstantieerd/vernietigd wat de snelheid ten goede komt. Ik denk dat dit hiervoor een uitstekende oplossing is.
Hmm... bij een chatprogramma denk ik vooral aan veel openstaande connecties die nu en dan data versturen; niet zozeer aan veel connecties die gemaakt/verwijderd moeten worden.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 28-08 12:00

Janoz

Moderator Devschuur®

!litemod

Soultaker schreef op 18 september 2002 @ 14:48:
Het enige echte voordeel van de eerste oplossing is dat je elke client in een apart object behandeld en dat de code daardoor duidelijk te lezen en makkelijk te schrijven is. Je moet dan echter wel rekeninghouden met het synchroniseren van de gedeelde bronnen.


Dat is in java niet zo heel lastig. Waneer je synchronized als keyword bij je sentMessageToAll (of andere setter achtige methoden) ben je al klaar :)

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
Ik heb ook eens gestart met een chat programma te maken in java. Daartoe heb ik 2 threads gebruikt: 1 die luistert naar binnenkomende connecties en 1 die naar binnenkomende berichten luisterde. Maar het werd mij allemaal ietsiepietsie teveel :D

Intussen heb ik ook vernomen dat het systeem van 1 thread/client het beste zou werken, maar het meeste bronnen vraagt van uw OS.

Ooit ga ik daarmee nog eens herbeginnen ...

ps: op deze site ziet u een voorbeeldje van 1 thread/client

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:49
Poohbear schreef op 18 september 2002 @ 14:57:
Voor zover ik iets van java weet kan dat niet zomaar... alle I/O is blocking. (Maar ik weet er weinig van, dat is waar).
Ik heb de API even ingekeken en inderdaad is er (zoals verwacht) geen select-mechanisme. Wel kun je de available() methode gebruiken om (non-blocking) vast te stellen of een socket nieuwe data heeft (en dus wel of niet zou blocken bij een read call).

Dat betekent dus dat je elke socket afzonderlijk moet gaan zitten pollen; dan kun je beter aparte threads gebruiken waarschijnlijk.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:49
Ho - ik heb niet goed gekeken. In Java 1.4 bestaan er Selector objecten, die op SocketChannels kunnen selecten, vergelijkbaar met de traditionele select-call.

Verwijderd

Poohbear schreef op 18 september 2002 @ 15:11:
[...]


Hmm... bij een chatprogramma denk ik vooral aan veel openstaande connecties die nu en dan data versturen; niet zozeer aan veel connecties die gemaakt/verwijderd moeten worden.
Ik had de thread weer niet goed doorgelezen :) .
Er stond dat er een thread per client werd gemaakt. Nu weet ik niet hoeveel users er op komen, maar ik weet wel dat vele threads onderhouden ook niet goedkoop is (context switching).

Ik zat meer te denken om per operatie een thread te starten. Doordat deze in een pool zitten heb je niet meer de overhead van het creeren en vernietigen van threads.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15:49
Verwijderd schreef op 18 september 2002 @ 15:44:
Er stond dat er een thread per client werd gemaakt. Nu weet ik niet hoeveel users er op komen, maar ik weet wel dat vele threads onderhouden ook niet goedkoop is (context switching).
Normaal gesproken is dat een valide argument, maar de kans is groot dat elke thread 99,9% van tijd blockt op de socket die er bij hoort. Een chatter typt misschien een zin per 10 seconden, waarna die zin in een fractie van een seconde verwerkt wordt.

Van die vele threads zitten er dus maar heel erg weinig op een gegeven moment in de ready queue en van overmatige (en daardoor contra-productieve) context switching is dan niet zo snel sprake.

Blijft nog over dat het creeeren van een thread niet 'gratis' is. Hier staat echter tegenover dat een chatter de neiging heeft om een paar minuten (zoniet een uur of meer) verbondne te blijven, waardoor de kosten van het opstarten van de thread relatief klein zijn (ten op zichte van al het werk dat in die thread vericht wordt).

Al met al denk ik dat de threaded oplossing dus zo gek nog niet is, al zal de implementatie die voor optimale performance gaat uiteraard met select calls en non-blocking sockets (voor het versturen van data) werken.

  • TheOneLLama
  • Registratie: Oktober 2000
  • Laatst online: 20-01-2022

TheOneLLama

A llama like no llama before

Poohbear schreef op 18 september 2002 @ 14:57:
[...]


Voor zover ik iets van java weet kan dat niet zomaar... alle I/O is blocking. (Maar ik weet er weinig van, dat is waar).
Kijk ook eens naar: http://www.cs.berkeley.edu/~mdw/proj/java-nbio/
Sinds 1.4 is er wel "echte" non-blocking IO mogelijk, met een aparte "package" hiervoor bekent onder de naam "NIO" (new IO).

Hiervoor was het in de praktijk ook al mogelijk wat er op lijkt dmv. de "available()" method. (let op: theoretisch gezien hoeft dit niet altijd te werken en is het implementatie afhankelijk, ik ken echter maar 1 implementatie (de J2ME BlackBerry JVM) waar dit niet werkte).
<edit>
Het versturen van data is wel (ook) nog steeds "blocking".. je method blockt waarschijnlijk niet totdat je data daadwerkelijk verstuurd wordt (buffering ed) maar het nog steeds niet te vergelijken met non-blocking.
Zoals ik al zeg hierboven ik heb het over iets wat op non-blocking lijkt, niet iets wat non-blocking is :)
</edit>


Enkele dingen (zoals het accepten van een connectie) zijn dan echter nog steeds blocking. Voor een chat applet lijkt me dat geen echte ramp, tot iemand op TCP niveau een (D)DOS aanval gaat doen ofzo.

NIO kan wel volledig non-blocking werken :)

[ Voor 0% gewijzigd door TheOneLLama op 18-09-2002 16:36 . Reden: toevoeging voor versturen ]

Opera OpenOffice.org Jabber Psi jabber://llama@mordax.com

Pagina: 1