Ilość wątków w napisanym programie

0

Wątki, o czym z pewnością nie trzeba nikogo przekonywać potrafią wiele ułatwić, jednak z tego co słyszałem duża ilość wątków może zamulać...
chciałem się zapytać czy rzeczywiście tworzenie wielu wątków tak bardzo zamula (mówiąc wielu mam na myśli kilkuset), czytałem sobie kiedyś Thinking in Java 3 i nie pamiętam aby autor wspominał tam o takim problemie

0

jeden wątek bez specjalnego wsparcia ( było nie dawno na forum ) może wykorzystać tylko jeden rdzeń ( lub jeden z jedno rdzeniowych procesorów )

tak więc by wykorzystać n rdzeniowego ( lub ogólnie n rdzeni w kilku procesorach ) najlepiej mieć n wątków

gdy na jeden rdzeń przypada więcej niż jeden wątek zaczynają się problemy, więc system przydziela wątek do rdzenia na skrawek sekundy, po tym skrawku rdzeń obrabia następny wątek i tak w kółko, im większy priorytet tym dłużej proces mieli się na rdzeniu ( popatrz sobie chociażby na "Czas procesora" w windowsowym menadżerze procesów, jest to ogólny czas przez jaki dany program ( czasy jego wszystkich wątków są tam zsumowane o ile się nie mylę ) używał procesora )

dobrze mówię ?

a co ty takiego robisz że ci paręset wątków wyłazi ?

0

Tzn. nie robię raczej nic specjalnego, chce się pobawić z aplikacją klient-serwer i jak patrzyłem na kody które są zasugerowane na java.sun.com w tutorialu na temat połączeń internetowych tam każdemu klientowi przedzielany jest jeden wątek, więc ilość użytkowników daje nam ilość wątków

ponadto chciałem skorzystać z Object(Input/Output)Stream do przesyłu danych przez internet (jasna sprawa że liczby stało czy zmiennoprzecinkowe, obiekty tablice czy inne trudno wysyłać przez strumienie bajtów lub znaków) i o ile jest tam metoda służąca do wyciągania ilości bajtów które można wyciągnąć ze strumienia to nie znalazłem metody do sprawdzania czy lub ile obiektów można stamtąd wyciągnąć, a ponieważ metody wyciągające coś ze strumieni przerywają wykonanie programu czekając na resztę danych które mają wyciągnąć tak więc program na serwerze mógłby się zatrzymywać na długie okresy czasu (np. przesyłanie plików graficznych itp.) stąd pomyślałem, że nasłuchiwanie dla każdego użytkownika musiałoby mieć osobny wątek bo inaczej serwer po prostu by stał w miejscu, jednak stwierdziłem że nie jest to najlepsze rozwiązanie stąd zadałem pytanie na forum

W ten sposób po stronie serwera mielibyśmy: 1 wątek na nasłuchiwanie połączenia bo metoda accept klasy ServerSocket też przerywa działanie programu, 2 * n wątków związanych z użytkownikami i jeden wątek na logikę aplikacji

Domyślam się że jest to błędne rozwiązanie, skoro już się tak rozpisałem prosiłbym o wskazówki jak rozwiązać taki problem

0

Poczytaj o nio i jego uzyj.

http://rox-xmlrpc.sourceforge.net/niotut/
Tutaj znajdziesz jakis artykul, ktory akurat omawia architekture client-server

0

Dziękuje, chciałbym jednak napomknąć że jestem stosunkowo nową osobą zajmującą się aktywnie programowaniem w Javie (kiedyś czytałem sobie kawałek książki) dopiero teraz zaczynam coś programować tak poważniej, i nie chciałbym w związku z tym uczyć się za dużo naraz, żeby wszystko w miarę zrozumieć

Mam rozumieć że przy pomocy starego IO nie można zrealizować tego o czym mówiłem w sposób o jakim mówiłem?

Może jeszcze jakieś konkrety?

Z góry dzięki za pomoc

0

w głównym wątku programu wykryj czy klient coś przysyła i wywołaj wątek który sprawdzi który to był, ten wątek prześle dane do wątku danego klienta który przemieli dane i wypluje to co serwer ma klientowi wysłać jako odpowiedź ?

0

Pomimo że bardzo chciałem nie rozumiem prezentowanej przez Ciebie idei, jeśli mógłbyś trochę jaśniej...

0

błeeee =(

  1. podłącza się klient
  • serwer szykuje dla niego wątek
  • serwer wysyła klientowi ID wątku
  1. klient wysyła dane + otrzymane ID
  • serwer tworzy wątek pomocniczy
  • wątek pomocniczy wygrzebuje ID, wybiera wątek, daje do wątku klienta dane
  • wątek klienta obrabia dane i daje serwerowi do wysłania ( np wywołuje jakąś funkcję )
  • serwer wysyła dane w odpowiednim połączeniu
  1. klient się odłącza
  • serwer morduje wątek klienta

takie coś ?

0

z tego co rozumiem z Twojego opisu dalej jest tworzone 2 * n wątków (czyli przy założeniu że klientów jest wielu kilkaset), gdzie n to liczba użytkowników, bo n wątków klientów i n wątków pomocniczych, ponadto nie widzę potrzeby przydzielania id wątkom obsługującym klientów gdyż wątek może przyjmować za argument obsługiwanego klienta poprzez Socket

Ogólnie ja myślałem o schemacie:
Serwer akceptuje połączenie metodą accept i tworzy nowy wątek który reprezentuje obsługiwanego klienta.
Wątek klienta sam w sobie tworzy wątek pomocniczy(związany z metodami blokującymi działanie programu) do nasłuchiwania czy nie nadeszły dane, które ginęłyby wraz z wątkiem obsługiwania klienta, wątek obsługujący klienta wykonywałby jakieś zsynchronizowane operacje na obiekcie reprezentującym stan (np. stan rozmowy na czacie) i tyle

po przeczytaniu fragmentu z podanego powyżej linka zastanawiam się o NIO, martwią mnie problemy z niekompatybilnością o których wspomina autor tamtego tutoriala
martwi mnie również że póki co niewiele zrozumiałem z tego tutoriala :), ale przeczytam jeszcze raz i myślę że będzie ok :)

0

Pamiętaj, że z każdym uruchomionym wątkiem javowym związany jest "prawdziwy" wątek. To, jak bardzo będzie zamulać przy dużej liczbie wątków zależy głównie od systemu operacyjnego. Na tym samym komputerze, pod Linuksem można spokojnie odpalić kilka razy więcej wątków niż na Windowsie(kiedyś robiłem testy i dopiero przy 2000 wątkach(nic nierobiących) poczułem, że system zwalnia, natomiast pod Windowsem taki efekt był widoczny przy około 300).

I nie chodzi tutaj o procesor, a raczej o RAM. Wątek, który czeka na wejście/wyjście nie zużywa procesora. Tak więc stwierdzenie "najlepiej mieć tyle wątków ile procesorów" jest całkowicie nieprawdziwe w przypadku serwerów. Najlepiej stworzyć sobie jakąś stałą(np. 50) pulę wątków, które obsługują żądania

0

czyli klient będzie musiał oczekiwać na zwolnienie jakiegoś wątku ?

a jakie tam 2 *n ? wątek pomocniczy byłby po to żeby serwer mógł działać dalej podczas sprawdzania danych, co raczej długo nie będzie trwać więc byłby to tymczasowy

0

@Luno: przejrzałem sobie pobieżnie metody klas pakietów z NIO ale nie widzę nic co pomogłoby mi odbierać z sieci gotowe zdeserializowane obiekty

Tak przy okazji nie ma sposobu na to żeby kontrolować proces serializowania i deserializowania danych?
mam na myśli sprawdzić czy dany ciąg można zserializować, czy jest wystarczający, ile obiekt zajmuje bajtów po serializacji etc.?

@__krzysiek85: mówisz, że chodzi o RAM, obciążenie RAM-u na tyle żeby system zaczął zwalniać rozumiem jako wrzucenie do niego takiej ilości danych aby OS zaczął stronicować RAM... w innym przypadku nie widzę powodu dlaczego miałby nawalać
nie wiem jak tworzone są "prawdziwe" wątki i ile miejsca zajmują, nie wiem również kiedy robiłeś swój test, ale zakładając że mamy do dyspozycji 1 GB ramu (system mi zajmuje po uruchomieniu 30% z tego), to wypchanie reszty ramu 2000 nic nie robiącymi wątkami wydaje mi się trochę dziwne
Bo przypada ponad 300 KB na wątek

ok, pula 50 wątków może być niezłym pomysłem, ale z tego co rozumiem wszystkie 50 ma nasłuchiwać, w moim wypadku wykonywać funkcję readObject, teraz załóżmy że klient zanim skończy wysyłać dane rozłączy się z jakiegoś powodu, wątek staje się zupełnie bezużyteczny bo jest w trakcie odczytywania informacji która już nie nadejdzie i z 50 wątków robi się 49...
można naturalnie go ubijać gdy w pewnym momencie się zorientujemy że odczytuję już długi czas i skończyć nie może...

ale nie o to chodzi, cały problem jaki teraz widzę polega na tym że jeżeli chcemy jakiemuś żądaniu przydzielić wątek, to musimy to żądanie odebrać..., a żeby je odebrać musimy czekać ze wszystkimi metodami readObject (bo moje założenie dotyczy wykorzystania właśnie tej metody) na stumieniach wszystkich gniazd potencjalnych klientów, innymi słowy nie widzę chwilowo możliwości stworzenia puli iluś wątków i obsługiwania żądań..., po potrzebujemy tylu wątków ilu jest klientów aby móc nasłuchiwać

Przy pracy na bajtach mamy sobie metodę avalaible i wszystko pięknie będzie działać bez czekania jeśli tylko chcemy: jednym wątkiem podłączamy użytkowników, jednym wątkiem nasłuchujemy żądania i nawet tym samym możemy je obsługiwać... ale tutaj użytkownicy mogliby ucierpieć, więc w tym wypadku warto zrobić wspomnianą pulę wątków do obsługi żądań...

@Potwoor_: tymczasowy ale dla każdego użytkownika jeden bo każde gniazdo trzeba nasłuchiwać, nieważne jak długi ważne że ktoś nim musi zarządzać.

PS. wpadła mi idea do głowy trochę dziwna ale w sumie może niezła
Ponieważ używając klas Socket i ServerSocket korzystam z TCP/IP, który zapewnia poprawność przesłanych danych, więc gdy Klient będzie wiedział że skończył wysyłać, wysyła na inny port informacje że wysłanie komunikatu zostało ukończone i wtedy spokojnie bez narażenia serwera na przestoje można wywołać metodę readObject, przestoju nie będzie bo wiemy że użytkownik zakończył wysyłanie danego komunikatu
w ten sposób mamy:

  • wątek który odbiera przychodzące połączenia -> serwer
  • wątek który odczytuje komunikaty o zakończeniu wysłania obiektu, odbiera obiekt, uruchamia wątek obsługujący żądanie
  • pula wątków do obsługi żądań

Co myślicie o pomyśle?

0

No niby tak tylko, ze w tym wypadku klient musialby po kazdym wyslaniu pakietu laczyc sie z serwerem, wysylac pakiet potwierdzajacy i rozlaczac sie aby nastepny klient mogl sie podlaczyc :/
Bo z tego co ja sie orientuje (ale moze sie myle bo juz od dawna nie bawilem sie sieciami), to do jednego socketu moze byc podlaczony tylko jeden klient?

0

tak na jednym sockecie może być tylko jeden użytkownik... ale socket jest tworzony w "oparciu" o numer ip, inny numer ip inny socket
dla każdego klienta tworzysz nowy socket... tak byś tworzył po prostu 2 sockety dla każdego na różnych portach i byś nie rozłączał się przy tym
jeden np. na porcie 9000 drugi na 9001,

0

przeczytałem o NIO ze wskazanego tutoriala, jakoś nie widzę jakichś jego cudownych właściwości, z tego co widzę to taka (nawet IMO niezbyt wygodna) nakładka w której jest tylko więcej do nauki

zimi napisał(a)

o ile jest tam metoda służąca do wyciągania ilości bajtów które można wyciągnąć ze strumienia to nie znalazłem metody do sprawdzania czy lub ile obiektów można stamtąd wyciągnąć, a ponieważ metody wyciągające coś ze strumieni przerywają wykonanie programu czekając na resztę danych które mają wyciągnąć tak więc program na serwerze mógłby się zatrzymywać na długie okresy czasu

Trochę nakłamałem jak się okazało, w prawdzie nie ma metod które pozwalają sprawdzić czy obiekt jest gotowy do deserializacji, ale metoda readObject wyrzuca wyjątek który może sugerować że obiekt nie jest gotowy, metoda również nie czeka na zakończenie wysyłania obiektu tylko gdy stwierdzi że nie może wyrzuca jakiś wyjątek

to tyle, dzięki wszystkim za pomoc

1 użytkowników online, w tym zalogowanych: 0, gości: 1