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?

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:

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?

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.

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:

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) );
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

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
   }

   
}

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