Rozróżnianie wątków

Rozróżnianie wątków
0

Witam, stworzyłem server obsługujący kilka wątków naraz i pojawił się u mnie problem z ich rozróżnieniem. Mianowicie do identyfikacji danego wątku mogę posłużyć się Thread.currentThread(). Wątki mam zapisane w tablicy threads, zatem mogę po kolei przechodzić tablicę i sprawdzać, czy danych wątek pokrywa się z Thread.currentThread(). Jednak wydaje mi się, że to nie jest zbyt dobre rozwiązanie, czy ktoś ma jakieś sugestie w jaki sposób można to zastąpić? A może jednak stosować tę metodę? Dodam, że jest to server obsługujący kilka wątków i muszę wyświetlać różne informację różnym klientom i dlatego potrzebuję je rozróżniać. Czy może istnieje jakiś inny sposób żeby robić to umyślnie?

artur52
  • Rejestracja:ponad 10 lat
  • Ostatnio:9 miesięcy
  • Lokalizacja:Warszawa
  • Postów:223
0

Może po prostu nadawaj im nazwy a potem wywałaj thread.getName ? :)

0

No ok, to w zasadzie też mogę używać Thread.currentThread().getId(). Zastanawia mnie jedna rzecz, weźmy przykładowo, że mam coś takiego:

Kopiuj
os = new PrintStream(clientSocket.getOutputStream());
synchronized (this)
			{
				for (int i = 0; i < liczbawątków; i++)
				{
					threads[i].os.println(Thread.currentThread().getId());
				}
			}

Wywołanie tego w run nie jest raczej dobrym pomysłem, bo zostanie wykonane przez każdy wątek. Celem oczywiście jest wyświetlenie każdemu klientowi jego numeru ID. I teraz pytanie, jak wykonywać takie operacje w run, ponieważ połączenie musi być z nimi nadal utrzymywane?

0

I jeszcze jedno pytanie - czy ktoś orientuje się w jaki sposób użyć listy, aby była ona ogólna dla wszystkich wątków? Mianowicie na przykład po usunięciu elementów w jednym wątku, w drugim też będą one usunięte?

0

Trochę czytałem o tym, na przykład o takim rozwiązaniu List<String> users = Collections.synchronizedList(new ArrayList<String>());, ale chciałbym poznań wasze zdanie, jaki sposób jest najlepszy.

0
głuchyaa napisał(a):

Celem oczywiście jest wyświetlenie każdemu klientowi jego numeru ID. I teraz pytanie, jak wykonywać takie operacje w run, ponieważ połączenie musi być z nimi nadal utrzymywane?

Troszkę nie rozumiem co chcesz osiągnąć?
Chcesz utrzymywać jeden wątek per klient? Imo nie tędy droga.
Jeżeli planujesz coś większego to ilością wątków zagłodzisz system.
Nie lepiej by było użyć thread pool i zwalniać wątki zamiast trzymać zajęte per klient?
Opisz proszę dokładniej jakie masz wymagania.

czytałem o tym, na przykład o takim rozwiązaniu List<string> users = Collections.synchronizedList(new ArrayList<string>());,

Jeżeli to ma być lista w której zarejestruje się każdy aktywny wątek, to polecił bym CopyOnWriteArrayList.
modyfikacje są kosztowniejsze, ale za to nie ma narzutu na synchronizację przy odczycie.

0
Świetny Orzeł napisał(a):

Troszkę nie rozumiem co chcesz osiągnąć?
Chcesz utrzymywać jeden wątek per klient? Imo nie tędy droga.
Jeżeli planujesz coś większego to ilością wątków zagłodzisz system.
Nie lepiej by było użyć thread pool i zwalniać wątki zamiast trzymać zajęte per klient?
Opisz proszę dokładniej jakie masz wymagania.

Server ma implementować prostą grę, opierającą się na wysyłaniu komunikatów z servera do klienta i vice versa, która rusza po dodaniu 9 klientów, zatem maksymalnie trzeba obsłużyć 9 wątków. I właśnie brałem pod uwagę, tak jak wspomniałeś utrzymywanie jednego wątku per klient. Czy jednak lepiej sprawdzi się wspomniana przez Ciebie metoda?

M9
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 6 lat
0

Dla tak małej ilości klientów nie masz co obawiać się zagłodzenia i nie ma znaczenia czy sobie stworzysz pule wątków o ograniczonym limicie czy nawet nie będziesz tego kontrolował. Co innego gdybyś pisał coś wysoce skalowalnego.

0
margor90 napisał(a):

Dla tak małej ilości klientów nie masz co obawiać się zagłodzenia i nie ma znaczenia czy sobie stworzysz pule wątków o ograniczonym limicie czy nawet nie będziesz tego kontrolował. Co innego gdybyś pisał coś wysoce skalowalnego.

Wtedy to już chyba najlepiej użyć NIO.

Świetny Orzeł napisał(a):

Jeżeli to ma być lista w której zarejestruje się każdy aktywny wątek, to polecił bym CopyOnWriteArrayList.
modyfikacje są kosztowniejsze, ale za to nie ma narzutu na synchronizację przy odczycie.

Ogólnie mam trochę z tym problem, zastanawiam się w jaki sposób umieszczać zasoby, które mają być modyfikowane przez wątki i te zmiany mają być przez nie widoczne. Mianowicie każdy wątek tworzy sobie od nowa dany element, w tym przypadku posłużmy się tablicą, czy tak jak wspomnieliśmy CopyOnWriteArrayList i od nowa wykonuje na niej operacje. Mamy na przykład metodę, która przyjmuje jako argument ilość potasowanych kart, które zwraca. Po zwróceniu usuwa karty, które zostały rozdane. Dajmy na to naszym argumentem jest liczba 3. Jeden wątek powinien pobrać 3 z 52 potasowanych kart, a następny już 3 z 49, aby te same karty nie zostały rozdawane. Jednak wątki tworzą od nowa listę i wybierają z 52, zatem dochodzi do sytuacji w które karty są powtarzane u klientów.

SM
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 6 lat
  • Postów:52
0
głuchyaa napisał(a):

Jednak wątki tworzą od nowa listę i wybierają z 52, zatem dochodzi do sytuacji w które karty są powtarzane u klientów.

Najwyrazniej w zlym miejscu inicjalizujesz liste skoro jest na nowo inicjalizowana per watek. Zrob to raz i potem klientom udostepniaj tylko mozliwosc pobierania kart.

0

Mam dwie klasy, jedną z wątkiem, drugą z serverem. Czy dobrym sposobem jest zdefiniowanie ArrayList w klasie z serverem i przesłanie jej jako argumentu w konstruktorze domyślnym wątku, w momencie powoływania go do życia? Wtedy każdy z wątków otrzymałby tę samą tablicę. Tylko zastanawiam się w jaki sposób później operować na oryginale w run(), oczywiście o ile mój sposób jest ok. No chyba, że ktoś ma lepszy pomysł jak sobie poradzić z problemem opisanym w tym temacie?

0

Można wyjść od typowego czatu, dla architektury "wątek per klient" (chociaż ja bym użył NIO), powinno to wyglądać mniej-więcej tak:

Kopiuj
class Player extends Thread{
  Socket socket;
  Game game;

  List<Karta> kartyGracza;

  Player(Socket socket, Game game){...}

  void run(){
    String receivedData = socket.recv(); //blokujacy?
    game.onMessage( receivedData );
  }

  void send(String dataToSend){
    socket.send(dataToSend);
  }

}

class Game{
   List<Player> players;
   List<Karta> karty_w_puli;

   void onMessage(String receivedData){
       //logika gry, np czy karty sie zgadzaja itd
       // ...
       String dataToSend;
       //broadcast
       players.stream().forEach( player->player.send(dataToSend) );
   }
}

//serwer
Game game;
Socket clientSocket = serverSocket.accept();
game.players.add( new Player(clientSocket, game) );
SM
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 6 lat
  • Postów:52
0
Świetny Orzeł napisał(a):

Jeden wątek powinien pobrać 3 z 52 potasowanych kart, a następny już 3 z 49, aby te same karty nie zostały rozdawane. Jednak wątki tworzą od nowa listę i wybierają z 52, zatem dochodzi do sytuacji w które karty są powtarzane u klientów.

W takiej sytuacji powinienes miec cos na styl

Kopiuj
enum Server{
    INSTANCE;

    private final List<Card> playerCards= new CopyOnWriteArrayList<>();

    private void init(){
      // tu zainicjalizuj elementy listy 
    }

   public List<Card> sendCards( int amount){
     // zwroc "amount" losowych kart
   }
}

class Player implements Runnable{
    private Server server =Server.INSTANCE;

  public void run(){
     List<Card> cards =server.sendCards(3);
     // tu sobie rob cos dalej z tym kartami
   }

   
}

edytowany 1x, ostatnio: ShermanMg
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)