JavaRush /Blog Java /Random-PL /Tłumaczenie: 50 najpopularniejszych pytań do wywiadu wedł...
KapChook
Poziom 19
Volga

Tłumaczenie: 50 najpopularniejszych pytań do wywiadu według wątków. Część 2.

Opublikowano w grupie Random-PL
Druga część tłumaczenia oryginalnego artykułu. 50 najważniejszych pytań do wywiadu w temacie Java. Odpowiedzi dla nowicjuszy i doświadczonych programistów. Pierwsza część.
  1. Jak sprawdzić, czy wątek trzyma blokadę?

  2. Nie miałem pojęcia, że ​​można sprawdzić, czy wątek jest aktualnie zablokowany, dopóki nie natknąłem się na to pytanie w rozmowie telefonicznej. Java.lang.Thread ma metodę holdLock(), która zwraca wartość true wtedy i tylko wtedy, gdy bieżący wątek utrzymuje monitor na określonym obiekcie.
  3. Jak uzyskać zrzut wątku?

  4. Zrzut wątku pozwala dowiedzieć się, co wątek aktualnie robi. Istnieje kilka sposobów uzyskania zrzutu wątku, w zależności od systemu operacyjnego. W systemie Windows możesz użyć kombinacji ctrl + Break, w systemie Linux możesz użyć polecenia kill -3. Możesz także użyć narzędzia jstack; działa ono na identyfikatorze procesu, który możesz znaleźć za pomocą innego narzędzia jps.
  5. Jaki parametr JVM służy do kontrolowania rozmiaru stosu wątku?

  6. Jest to jeden z prostych parametrów -Xss używanych do kontrolowania rozmiaru stosu wątku w Javie.
  7. Różnice między synchronizacją a ReentrantLock?

  8. Były chwile, gdy jedynym sposobem na wzajemne wykluczenie było użycie słowa kluczowego synchronized, ale ma to kilka wad, takich jak brak możliwości rozszerzenia blokady poza metodę lub blok kodu itp. Java 5 rozwiązuje ten problem, zapewniając bardziej szczegółową kontrolę poprzez interfejs blokady. ReentrantLock to popularna implementacja blokady, która zapewnia blokadę takie samo podstawowe zachowanie i semantykę jak niejawny monitor, osiągane przy użyciu metod zsynchronizowanych, ale z ulepszonymi możliwościami.
  9. Biorąc pod uwagę 3 wątki T1, T2 i T3? Jak zaimplementować sekwencję T1, T2, T3?

  10. Spójność można osiągnąć na wiele sposobów, ale możesz po prostu użyć metody Join(), aby rozpocząć wątek po zakończeniu wykonywania innego wątku. Aby zaimplementować podaną sekwencję należy najpierw uruchomić ostatni wątek, a następnie wywołać metodę Join() w odwrotnej kolejności, czyli T3 wywołuje T2.join, a T2 wywołuje T1.join, więc T1 zakończy się pierwszy, a T3 ostatni .
  11. Do czego służy metoda wydajności?

  12. Metoda Yield to jeden ze sposobów poproszenia wątku o oddanie procesora, aby mógł zostać wykonany inny wątek. Jest to metoda statyczna i zapewnia jedynie, że bieżący wątek odda procesor, ale nie decyduje, do którego wątku zostanie skierowane wykonanie.
  13. Jaki jest poziom współbieżności ConcurrentHashMap?

  14. ConcurrentHashMap osiąga swoją skalowalność i bezpieczeństwo wątków, dzieląc rzeczywistą mapę na sekcje. Oddzielenie to osiąga się poprzez zastosowanie poziomu równoległości. Jest to opcjonalny parametr konstruktora ConcurrentHashMap, a jego wartość domyślna to 16.
  15. Co to jest semafor?

  16. Semafor to nowy typ synchronizatora. To jest semafor z licznikiem. Koncepcyjnie semafor kontroluje zestaw uprawnień. Każda funkcja require() blokuje, jeśli to konieczne, zanim uprawnienie stanie się dostępne, a następnie je uzyskuje. Każde wydanie() dodaje uprawnienie, potencjalnie zwalniając jednostkę przejmującą blokowanie. Jednak nie używa to rzeczywistych obiektów uprawnień; Semafor po prostu przechowuje liczbę dostępnych i działa zgodnie z nimi. Semafor służy do ochrony kosztownych zasobów, które są dostępne w ograniczonych ilościach, takich jak połączenie ze zbiorczą bazą danych.
  17. Co się stanie, jeśli kolejka puli wątków będzie już pełna i prześlesz zadanie?

  18. Jeśli kolejka puli wątków będzie pełna, przesłane zadanie zostanie „odrzucone”. Metoda Submit() metody ThreadPoolExecutor zgłasza wyjątek RejectedExecutionException, po czym wywoływana jest metoda RejectedExecutionHandler.
  19. Różnice między metodami przesyłania () i wykonywania () w puli wątków?

  20. Obie metody to sposoby przesyłania zadania do puli wątków, ale istnieje między nimi niewielka różnica. Execute (polecenie uruchamialne) jest zdefiniowane w interfejsie Executera i wykonuje dane zadanie w przyszłości, ale co ważniejsze, niczego nie zwraca. Z drugiej strony, Submit() jest metodą przeciążoną, może akceptować zadania Runnable i Callable i może zwracać obiekt Future, którego można użyć do anulowania wykonania i/lub oczekiwania na wynik obliczeń. Ta metoda jest zdefiniowana w interfejsie ExecutorService, który dziedziczy z interfejsu Executor, a każda klasa puli wątków, taka jak ThreadPoolExecutor lub ScheduledThreadPoolExecutor, dziedziczy te metody.
  21. Co to jest metoda blokowania?

  22. Metoda blokowania to metoda, która blokuje do czasu zakończenia zadania, na przykład metoda ServerSocket Accept() blokuje w oczekiwaniu na połączenie klienta. W tym przypadku blokowanie oznacza, że ​​sterowanie nie powróci do metody wywołującej, dopóki zadanie nie zostanie zakończone. Z drugiej strony istnieją metody asynchroniczne lub nieblokujące, które kończą się przed zakończeniem zadania.
  23. Czy wątek Swing jest bezpieczny?

  24. Mówiąc najprościej, nie, Swing nie jest bezpieczny dla wątków, ale musisz wyjaśnić, co przez to rozumiesz, nawet jeśli osoba przeprowadzająca rozmowę kwalifikacyjną nie pyta. Kiedy mówimy, że Swing nie jest bezpieczny dla wątków, zwykle mamy na myśli fakt, że jest to komponent, którego nie można modyfikować wieloma wątkami. Wszystkie zmiany w komponentach GUI muszą być wprowadzane w wątku AWT, a Swing zapewnia synchroniczne i asynchroniczne metody planowania takich zmian.
  25. Różnice między invokeAndWait i invokeLater?

  26. Są to dwie metody API Swing, które pozwalają programistom aktualizować komponenty GUI z wątków, a nie z wątku Menedżera zdarzeń. InvokeAndWait() synchronicznie aktualizuje komponent GUI, taki jak pasek postępu; za każdym razem, gdy nastąpi postęp, pasek musi zostać zaktualizowany, aby odzwierciedlić zmiany. Jeśli postęp jest śledzony w innym wątku, musi on wywołać metodę invokeAndWait() w celu przypisania wątku Event Dispatcher do aktualizacji tego komponentu. InvokeLater() to asynchroniczne wywołanie aktualizacji komponentów.
  27. Które metody API Swing są bezpieczne dla wątków?

  28. To pytanie ponownie dotyczy bezpieczeństwa Swing i wątków, chociaż komponenty Swing nie są bezpieczne dla wątków, istnieją metody, które można bezpiecznie wywoływać z wielu wątków. Wiem, że repaint() i revalidate() są bezpieczne dla wątków, ale istnieją inne metody w różnych komponentach Swing, takie jak metody setText() JTextComponent oraz metody Insert() i append() JTextArea.
  29. Jak tworzyć niezmienne obiekty?

  30. To pytanie może wydawać się nie mieć nic wspólnego z wielowątkowością i współbieżnością, ale tak jest. Niezmienność pomaga uprościć i tak już złożony kod równoległy. Niezmienny obiekt jest bardzo kosztowny dla programistów, ponieważ można go propagować bez żadnej synchronizacji. Niestety, Java nie ma adnotacji @Immutable, która sprawi, że obiekt będzie niezmienny, ponieważ programiści muszą ciężko pracować. Aby utworzyć obiekt niezmienny, należy postępować zgodnie z podstawami: inicjalizacja w konstruktorze, brak seterów, brak wycieków referencji, przechowywanie oddzielnych kopii obiektów zmiennych.
  31. Co to jest ReadWriteLock?

  32. Ogólnie rzecz biorąc, ReadWriteLock jest wynikiem techniki analizy blokad mającej na celu poprawę wydajności aplikacji równoległych. Jest to interfejs dodany w Javie 5. Działa w oparciu o parę powiązanych blokad, jedną dla operacji odczytu, drugą dla operacji zapisu. Blokada czytnika może być utrzymywana jednocześnie przez kilka wątków czytających, dopóki nie zabraknie pisarzy. Blokada pisania jest ekskluzywna. Jeśli chcesz, możesz zaimplementować interfejs ze swoim zestawem reguł lub możesz użyć ReentrantReadWriteLock, który obsługuje maksymalnie 65535 rekursywnych blokad zapisu i 65535 blokad odczytu.
  33. Co to jest zajęty obrót?

  34. Busy Spin to technika używana przez programistów w celu wymuszenia oczekiwania wątku pod pewnymi warunkami. W przeciwieństwie do tradycyjnych metod Wait(), Sleep() lub Yield(), które wymagają przekazania kontroli nad procesorem, ta metoda nie przekazuje procesora, a zamiast tego po prostu wykonuje pustą pętlę. Dlaczego ktoś miałby to zrobić? Aby zapisać pamięć podręczną procesora. W systemach wielordzeniowych możliwe jest, że zawieszony wątek będzie nadal wykonywany na innym rdzeniu, co oznacza przebudowę pamięci podręcznej. Aby uniknąć kosztownych przebudów, programista woli krócej czekać, korzystając z zajętego wirowania.
  35. Różnice między zmiennymi lotnymi i atomowymi?

  36. To dość interesujące pytanie, na pierwszy rzut oka zmienne lotne i atomowe wyglądają bardzo podobnie, ale nadal są różne. Zmienna Volatile gwarantuje, że zapis nastąpi przed jakimkolwiek kolejnym zapisem, ale nie gwarantuje niepodzielności. Na przykład operacja count++ nie stanie się niepodzielna tylko dlatego, że count jest zadeklarowana jako niestabilna. Z drugiej strony klasa AtomicInteger udostępnia metodę atomową do wykonywania tak złożonych operacji atomowo, na przykład getAndInkrement() jest atomowym zamiennikiem operatora inkrementacji, można go użyć do atomowego zwiększenia bieżącej wartości o jeden. Istnieją również wersje atomowe dla innych typów danych.
  37. Co się stanie, jeśli wątek zgłosi wyjątek w zsynchronizowanym bloku?

  38. To kolejne podchwytliwe pytanie dla zwykłych programistów Java. Bez względu na to, jak wyjdziesz z zsynchronizowanego bloku, albo normalnie, kończąc wykonywanie, albo nagle, zgłaszając wyjątek, wątek zwalnia nabytą blokadę, gdy wchodzi do zsynchronizowanego bloku. Jest to jeden z powodów, dla których wolę zsynchronizowany blok blokady od interfejsu, który wymaga szczególnej ostrożności podczas zwalniania blokady, zwykle osiąganej poprzez zwolnienie blokady w bloku final.
  39. Na czym polega podwójnie sprawdzana blokada Singleton?

  40. To jedno z najpopularniejszych pytań na rozmowach kwalifikacyjnych, a mimo to, pomimo jego popularności, szanse, że kandydat na nie odpowie, wynoszą co najwyżej 50%. W połowie przypadków nie udaje im się napisać kodu, a w drugiej połowie wyjaśnić, w jaki sposób został on uszkodzony i naprawiony w Javie 1.5. To stary sposób tworzenia singletonu bezpiecznego dla wątków, który próbuje zoptymalizować wydajność poprzez blokowanie tylko wtedy, gdy instancja singletonu jest tworzona po raz pierwszy, ale ze względu na złożoność i fakt, że został uszkodzony w JDK 1.4, osobiście mi się nie podoba To. Mimo to, nawet jeśli nie wolisz tego podejścia, warto poznać je z perspektywy rozmowy kwalifikacyjnej.
  41. Jak stworzyć Singleton bezpieczny dla wątków?

  42. To pytanie uzupełnia poprzednie. Jeśli powiesz, że nie lubisz podwójnego sprawdzania blokowania, osoba przeprowadzająca rozmowę będzie zmuszona zapytać o alternatywne sposoby stworzenia Singletona bezpiecznego dla wątków. I tak jest, możesz skorzystać z funkcji ładowania klas i inicjalizacji zmiennych statycznych, aby utworzyć instancję Singletona, lub możesz skorzystać z potężnego typu wyliczeniowego.
  43. Wymień 3 zwyczaje, których przestrzegasz w programowaniu równoległym?

  44. To moje ulubione pytanie, ponieważ uważam, że podczas pisania kodu równoległego należy przestrzegać pewnych zasad, co pomaga w wydajności, debugowaniu i obsłudze. Poniżej znajdują się 3 najlepsze zasady, których moim zdaniem powinien przestrzegać każdy programista Java:
    • Zawsze nadawaj swoim wątkom znaczące nazwy
    • Znalezienie błędu lub wyśledzenie wyjątku w kodzie równoległym jest dość trudnym zadaniem. OrderProcessor, QuoteProcessor lub TradeProcessor jest znacznie lepszy niż Thread-1. Wątek-2 i Wątek-3. Nazwa powinna odzwierciedlać zadanie realizowane przez wątek. Wszystkie główne frameworki, a nawet JDK, przestrzegają tej zasady.
    • Unikaj blokowania lub zmniejsz zakres synchronizacji
    • Blokowanie jest drogie, a przełączanie kontekstu jest jeszcze droższe. Staraj się w miarę możliwości unikać synchronizacji i blokowania, a zredukujesz sekcję krytyczną do wymaganego minimum. Dlatego wolę blokowanie czasowe od metody czasowej, ponieważ daje ona całkowitą kontrolę nad zakresem blokowania.
    • Pomiędzy synchronizatorami a czekaniem i powiadamianiem wybierz synchronizatory
    • Po pierwsze, synchronizatory takie jak CountDownLatch, Semaphore, CyclicBarrier czy Exchanger upraszczają kodowanie. Bardzo trudno jest wdrożyć złożony przepływ kontroli za pomocą funkcji oczekiwania i powiadamiania. Po drugie, klasy te są pisane i utrzymywane przez najlepszych w branży i istnieje duża szansa, że ​​w przyszłych wydaniach JDK zostaną zoptymalizowane lub zastąpione lepszym kodem. Korzystając z narzędzi do synchronizacji wysokiego poziomu, automatycznie zyskujesz wszystkie te korzyści.
    • Pomiędzy Kolekcją współbieżną a Kolekcją zsynchronizowaną wybierz Kolekcję współbieżną
    • To kolejna prosta zasada, której łatwo przestrzegać i czerpać korzyści. Kolekcje współbieżne są bardziej skalowalne niż ich zsynchronizowane odpowiedniki, dlatego lepiej jest ich używać podczas pisania kodu równoległego. Więc następnym razem, gdy będziesz potrzebować mapy, pomyśl o ConcurrentHashMap, zanim pomyślisz o Hashtable.
  45. Jak wymusić rozpoczęcie wątku?

  46. To jest pytanie, jak wymusić działanie zbierania śmieci. Krótko mówiąc, nie ma mowy, możesz oczywiście wykonać zapytanie za pomocą System.gc(), ale to niczego nie gwarantuje. Nie ma absolutnie żadnego sposobu, aby wymusić uruchomienie wątku w Javie, jest to kontrolowane przez program planujący wątki, a Java nie udostępnia żadnego interfejsu API do kontrolowania tego. Ta część Java jest nadal losowa.
  47. Co to jest framework Fork/Join?

  48. Struktura Fork/Join wprowadzona w JDK 7 to potężne narzędzie, które pozwala programiście wykorzystać wiele procesorów nowoczesnych serwerów. Jest przeznaczony do pracy, którą można rekurencyjnie podzielić na małe cząstki. Celem jest wykorzystanie całej dostępnej mocy obliczeniowej w celu zwiększenia wydajności aplikacji. Istotną zaletą tego frameworka jest to, że wykorzystuje algorytm kradzieży pracy (od pracy – pracy i kradzieży – do kradzieży). Wątki robocze, którym skończyły się zadania, mogą kraść zadania z innych wątków, które są nadal zajęte.
  49. Jaka jest różnica między wywołaniami funkcji Wait() i Sleep()?

  50. Chociaż zarówno oczekiwanie, jak i uśpienie stanowią rodzaj pauzy w aplikacji Java, są to urządzenia do różnych potrzeb. Wait służy do komunikacji w wątku wewnętrznym, blokuje się, jeśli warunek oczekiwania jest prawdziwy i czeka na powiadomienie, jeśli działania innego wątku spowodują, że warunek oczekiwania będzie fałszywy. Z drugiej strony metoda Sleep() po prostu rezygnuje z procesora lub wstrzymuje wykonywanie bieżącego wątku na określony czas. Wywołanie funkcji Sleep() nie zwalnia blokady utrzymywanej przez bieżący wątek.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION