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ęść 1.

Opublikowano w grupie Random-PL
Pierwsza część tłumaczenia oryginalnego artykułu. 50 najważniejszych pytań do wywiadu w temacie Java. Odpowiedzi dla nowicjuszy i doświadczonych programistów. Druga część. Uwaga: artykuł okazał się duży, dlatego nie mieści się w jednym temacie. Poza tym to dość skomplikowane, próbowałem jak mogłem, żeby to znaleźć w Google, ale mimo to. Dlatego prosimy uczestników, którzy biegle władają językiem angielskim, aby zapoznali się z oryginałem i porównali go z tłumaczeniem, na wypadek, gdyby coś źle zrozumieli lub źle przetłumaczyli. Z góry dziękuję. Podczas każdej rozmowy kwalifikacyjnej, niezależnie od tego, czy jesteś starszy czy młodszy, doświadczony czy początkujący, będziesz musiał zmierzyć się z kilkoma pytaniami dotyczącymi wątków, równoległości i wielowątkowości. W rzeczywistości wbudowana obsługa współbieżności jest jedną z największych zalet Javy i pomogła jej zdobyć popularność zarówno wśród przedsiębiorców, jak i programistów. Najbardziej lukratywne stanowiska programistów Java wymagają doskonałych umiejętności wielowątkowych i doświadczenia w tworzeniu, debugowaniu i dostrajaniu aplikacji o wysokiej wydajności i małych opóźnieniach. Dlatego jest to jedna z najbardziej poszukiwanych umiejętności podczas rozmów kwalifikacyjnych. W typowym wywiadzie w języku Java osoba przeprowadzająca rozmowę powoli zaczyna od podstawowych koncepcji wątków, zadając pytania takie jak: dlaczego wątki są potrzebne, jak je tworzyć, jaki sposób ich tworzenia jest lepszy, dziedziczyć z Thread lub implementować Runnable, a następnie powoli przechodzi na trudności związane ze współbieżnością, trudności napotykane podczas tworzenia aplikacji równoległych, narzędzia współbieżności wysokiego poziomu wprowadzone w JDK 1.5, zasady i wzorce projektowe aplikacji równoległych oraz klasyczne problemy wielowątkowości. Tylko dlatego, że nie wystarczy znać podstawy wielowątkowości, musisz wiedzieć, jak radzić sobie z problemami współbieżności, takimi jak zakleszczenie, warunki wyścigu, niespójność pamięci i różne problemy związane z bezpieczeństwem wątków. Umiejętności te są dokładnie testowane, co przedstawia różne wyzwania związane z wielowątkowością i współbieżnością. Wielu programistów Java zazwyczaj po prostu czyta pytania przed samą rozmową kwalifikacyjną, co nie jest złe, ale powinieneś to zrozumieć. Poza tym gromadzenie pytań i wykonywanie tych samych ćwiczeń marnuje dużo czasu, dlatego stworzyłem tę listę.
  1. Co to jest wątek w Javie?

  2. Wątek jest niezależną ścieżką wykonania. Jego celem jest wykorzystanie wielu procesorów dostępnych w maszynie. Używając wielu wątków, możesz przyspieszyć zadania obciążające procesor. Na przykład, jeśli wykonanie zadania przez jeden wątek zajmuje 100 milisekund, można użyć 10 wątków, aby skrócić to zadanie do 10 milisekund. Java zapewnia doskonałe wsparcie dla wielowątkowości na poziomie języka i to zresztą jest jedną z jej największych zalet.
  3. Różnica między wątkami i procesami w Javie?

  4. Нить – это подмножество процесса, другими словами один процесс может содержать множество нитей. Два процесса исполняются на различных пространствах памяти, но все нити делят одно пространство. Не спутайте это с памятью стека, которая различная для каждой нити и используется для хранения локальных данных этой нити.
  5. Как создать нить?

  6. На уровне языка есть два способа создания нити. Объект класса java.lang.Thread представляет собой нить, но ей требуется задача для исполнения, которая является obiektом, реализующим интерфейс java.lang.Runnable. Так Jak класс Thread реализует интерфейс Runnable, вы можете переопределить метод run() унаследовав ваш класс от Thread Lub реализовав в нём интерфейс Runnable.
  7. Когда использовать Runnable и когда Thread?

  8. Это дополнение к предудыщему вопросу. Как мы знаем, нить можно создать унаследовавшись от класса Thread Lub реализовав интерфейс Runnable. Возникает вопрос, который из способов лучше и когда Jakой использовать? На этот вопрос легко ответь, если вы знаете, что Java не поддерживает множественное наследование классов, но позволяет реализовывать множество интерфейсов. Co означает, что лучше реализовывать Runnable, если вы хотите унаследоваться от другого класса.
  9. Różnica между методами start() и run()?

  10. Один из вопросов с подвохом из прошлого, но он всё ещё достаточно хорош, чтобы отличить поверхностное понимание многонитиевости в Java. Метод start() используется для запуска новой нити. Несмотря на то, что start() вызывает метод run() внутри себя, это не то же самое, что просто вызвать run(). Если вы вызываете run() Jak обычный метод, он вызывается в той же нити и ниJakая новая нить не запуститься, что происходит, когда вы вызываете метод start().
  11. Различия Runnable и Callable?

  12. Оба интерфейса представляют задачи, которые предназначены для выполнения в отдельных нитях. Runnable существует ещё с JDK 1.0, а Callable был добавлен в JDK 1.5. Главное их различие заключается в том, что метод call() у Callable может возвращать значения и выбрасывать исключения, что невозможно в методе run() у Runnable. Callable возвращает obiekt Future, который может содержать результат вычислений.
  13. Различия между CyclicBarrier и CountDownLatch?

  14. Хоть оба эти синхронизаторы позволяют нитям дожидаться друг друга, главное различие между ними в том, что вы не можете заново использовать CountDownLatch после того, Jak его счётчик достигнет нуля, но вы можете использовать CyclicBarrier снова, даже после того, Jak барьер сломается.
  15. Co такое модель памяти Java?

  16. Модель памяти – это набор правил и указаний, которые позволяют Java программам действовать детерминировано среди множества архитектур памяти, процессора и операционной системы. Это особенно важно в случае многонитиевости. Модель памяти предоставляет гарантии того, что изменения, произведённые одной нитью, будут видны для других, одна из них – отношение happens-before (случалось ранее). Это отношение определяет несколько правил, которые позволяют программистам предвидеть и определять поведение параллельных программ. Например happens-before гарантирует:
    • Каждое действие в нити случается раньше любого действия в этой нити, которое следует в программном порядке, это также известно, Jak правило программного порядка.
    • Разблокировка монитора случается раньше каждой последующей блокировки того же самого монитора, также известно, Jak правило блокировки Монитора.
    • Запись volatile поля случается раньше каждого последующего чтения этого поля, правило изменчивой переменной.
    • Вызов Thread.start() в нити случается раньше, чем любая другая нить замечает, что нить была остановлена, либо после удачного Thread.join(), либо если Thread.isAlive() возвращает false, правило Thread.start().
    • Прерывание нити из другой нити случается раньше, чем прерванная нить заметит прерывание (либо от выброса InterruptedException, либо от проверки isInterrupted()), правило прерывания нити.
    • Окончание конструктора obiektа случается раньше, чем запуск финализатора для этого obiektа, правило Финализатора.
    • Если А случается раньше В, и В случается раньше С, значит А случается раньше С, что значит happens-before гарантирует транзитивность.
  17. Co такое volatile переменная?

  18. Volatile – специальный модификатор, который может применяться только к атрибутам. В параллельных Java программах изменения, произведённые различными нитями на атрибутах, не видны для остальных при отсутствии синхронизатора. Volatile переменная гарантирует, что запись будет осуществляться до последующего чтения, что сказано в правиле изменчивой переменной в предыдущем вопросе.
  19. Co такое ните-безопасность? Безопасный ли класс Vector?

  20. Ните-безопасность – свойвство obiektа Lub kodа, которое гарантирует, что при исполнении Lub использовании несколькими нитями, kod будет вести себя, Jak предполагается. Например ните-безопасный счётчик не пропустит ни один счёт, если тот же экземпляр счётчика используется среди нескольких нитей. Очевидно, можно разделить классы коллекций на две категории, ните-безопасные и не-ните-безопасные. Vector ните-безопасен и достигает этого синхронизацией методов, которые изменяют состояние Vector’a, с другой стороны его коллега ArrayList не-ните-безопасен.
  21. Co такое состояние гонки (race condition)?

  22. Состояние гонки – причина трудноуловимых багов. Как сказано в самом названии, состояние гонки возникает из-за гонки между несколькими нитями, если нить, которая должна исполнятся первой, проиграла гонку и исполняется вторая, поведение kodа изменяется, из-за чего возникают недетерменированные баги. Это одни из сложнейших к отлавливанию и воспроизведению багов, из-за беспорядочной природы гонок между нитями. Пример состояния гонки – беспорядочное исполнение.
  23. Как остановить нить?

  24. Я всегда говорил, что Java предоставляет богатые API для всего, но, по иронии судьбы, не предоставляет удобных способов остановки нити. В JDK 1.0 было несколько управляющих методов, например stop(), suspend() и resume(), которые были помечены Jak deprecated в будущих релизах из-за потенциальных угроз взаимной блокировки, с тех пор разработчики Java API не предприняли попыток представить стойкий, ните-безопасный и элегантный способ остановки нитей. Программисты в основном полагаются на факт того, что нить останавливается сама, Jak только заканчивает выполнять методы run() Lub call(). Для остановки вручную, программисты пользуются преимуществом volatile boolean переменной и проверяют её oznaczający в каждой итерации, если в методе run() есть циклы, Lub прерывают нити методом interrupt() для внезапной отмены заданий.
  25. Co происходит, когда в нити появляется исключение?

  26. Это один из хороших вопросов с подвохом. Простыми словами, если исключение не поймано – нить мерта, если установлен обработчик непойманных исключений, он получит колбек. Thread.UncaughtExceptionHandler – интерфейс, определённый Jak вложенный интерфейс для обработчиков, вызываемых, когда нить внезапно останавливается из-за непойманного исключения. Когда нить собирается остановится из-за непойманного исключения, JVM проверит её на наличие UncaughtExceptionHandler, используя Thread.getUncaughtExceptionHandler(), и вызовет у обработчика метод uncaughtException(), передав нить и исключение в виде аргументов.
  27. Как поделиться данными между двумя нитями?

  28. Вы можете делиться данным между нитями, используя общий obiekt Lub параллельные структуры данных, типа BlockingQueue.
  29. Различия между notify и notifyAll?

  30. Это ещё один из вопросов с подвохом, так Jak за одним монитором могут наблюдать несколько нитей, Java API разработчики предоставляют метод для уведомления об изменении его состояния только одной Lub сразу всех нитей, но они предоставляют только половину реализации. У метода notify() не реализован способ выбора определённой нити, поэтому он полезен только когда вы точно знаете, что всего одна нить ожидает. С другой стороны, notifyAll() уведомляет все нити и позволяет им побороться за монитор, что гарантирует, что по крайней мере одна нить продвинется дальше.
  31. Почему wait, notify и notifyAll не в классе Thread?

  32. Это вопрос, относящийся к дизайну, который проверяет, что кандидат думает о существующих системах Lub думал ли он когда-либо о чём-то схожем, но выглядящем неуместно поначалу. Coбы ответить на этот вопрос, вам нужно предоставить несколько причин, почему эти методы удобнее реализовывать в классе Object, и почему не в классе Thread. Первая очевидная причина – Java поддерживает lock на уровне obiektов, а не на уровне нитей. Любой obiekt имеет lock, который получает нить. И если нити нужно ждать определённый lock, есть смысл в том, чтобы вызвать wait() на obiekt, чем на эту нить. Если бы wait() был объявлен в классе Thread, было бы не ясно, Jakой lock нить ждёт. Вкратце, так Jak wait, notify и notifyAll работают на уровне lock, удобнее объявить их в классе Object, потому что lock относится к obiektу.
  33. Co такое ThreadLocal переменная?

  34. ThreadLocal переменные – специальный вид переменных, доступных Java программисту. Так же, Jak для состояний есть переменная состояния, для нитей есть ThreadLocal переменные. Это неплохой способ достичь ните-безопасности для затратных-для-создания obiektов, например вы можете сделать SimpleDateFormat ните-безопасным, используя ThreadLocal. Так Jak это затратный класс, его нежелательно использовать в локальной области, которая требует отдельных экземпляров на каждый вызов. Предоставляя каждой нити её собственную копию, вы убиваете двух зайцев. Во-первых, вы уменьшаете количество экземпляров затратных obiektов, используя по новой фиксированное количество экземпляров, и во-вторых, вы достигаете ните-безопасности, без потерь синхронизации и неизменяемости. Ещё один хороший пример локальной переменной у нити – класс ThreadLocalRandom, который уменьшает количество экземпляров затратных-для-создания obiektов Random в много-нитиевой среде.
  35. Co такое FutureTask?

  36. FutureTask представляет собой отменяемое асинхронное вычисление в параллельном Java приложении. Этот класс предоставляет базовую реализацию Future, с методами для запуска и остановки вычисления, методами для wniosekа состояния вычисления и извлечения результатов. Результат может быть получен только когда вычисление завершено, метод получения будет заблокирован, если вычисление ещё не завершено. Объекты FutureTask могут быть использованы для обёртки obiektов Callable и Runnable. Так Jak FutureTask реализует Runnable, его можно передать Executor’у на выполнение.
  37. Различие между interrupted и isInterrupted?

  38. Основное различие между interrupted() и isInterrupted() в том, что первый сбрасывает статус прерывания, а второй нет. Механизм прерывания в Java реализован с использованием внутреннего флага, известного Jak статус прерывания. Прерывание нити вызовом Thread.interrupt() устанавливает этот флаг. Когда прерванная нить проверяет статус прерывания, вызывая статический метод Thread.interrupted(), статус прерывания сбрасывается. Нестатический метод isInterrupted(), который используется нитью для проверки статуса прерывания у другой нити, не изменяет флаг прерывания. Условно, любой метод, который завершается, выкинув InterruptedException сбрасывает при этом флаг прерывания. Однако, всегда существует возможность того, что флаг тут же снова установится, если другая нить вызовет interrupt().
  39. Почему методы wait и notify вызываются в синхронизированном блоке?

  40. Основная причина вызова wait и notify из статического блока Lub метода в том, что Java API обязательно требует этого. Если вы вызовете их не из синхронизированного блока, ваш kod выбросит IllegalMonitorStateException. Более хитрая причина в том, чтобы избежать состояния гонки между вызовами wait и notify.
  41. Почему вы должны проверять состояние ожидания в цикле?

  42. Существует возможность того, что ожидающая нить получит ложные предупреждения и ложные вызовы пробуждения, если она не проверит состояние ожидания в цикле, она просто выйдет, даже если состояние не достигнуто. Когда ожидающая нить пробуждается, она не думает о том, что состояние, которое она ожидала, может все ещё оставаться в силе. Оно могло быть действительно в прошлом, но потом быть изменено после вызова метода notify() и перед тем Jak нить пробудилась. Поэтому всегда лучше вызывать wait() из цикла.
  43. Различия между synchronized и concurrent коллекциями?

  44. Хоть обе synchronized и concurrent коллекции предоставляют ните-безопасные коллекции, последняя является более масштабируемой. До Java 1.5 программистам были доступны только synchronized коллекции, которые становLubсь источником раздора, когда несколько нитей обращались к ним одновременно, что затрудняло масштабирование системы. Java 5 представила concurrent коллекции, например ConcurrentHashMap, которые не только предоставляют ните-безопасность, но также улучшают масштабируемость, используя современные техники, такие Jak lock stripping и partitioning internal table.
  45. Различия между Стеком и Кучей?

  46. Почему этот вопрос присутствует в вопросах о много-нитиевости? Потому что стек – участок памяти, тесно связанный с нитями. У каждой нити есть свой стек, которые хранит локальные переменные, параметры методов и стек вызовов. Переменная, хранящаяся в стеке одной нити, не видна для другой. С другой стороны, куча – общий участок памяти, который делится между всеми нитями. Объекты, неважно локальные Lub любого другого уровня, создаются в куче. Для улучшения производительности, нить обычно кэширует значения из кучи в свой стек, тут-то выползают volatile переменные. Volatile указывает нитям на то, что переменную нужно читать из главной памяти.
  47. Co такое пул нитей?

  48. kreacja нити затратно в плане времени и ресурсов. Если вы создаёте нить во время обработки wniosekа, это замедлит время отклика, также процесс может создать только ограниченное число нитей. Coбы избежать этих проблем, во время запуска Aplikacje создаётся пул нитей и нити повторно используются для обработки wniosekов. Этот пул нитей называется «thread pool», а нити в нём – рабочая нить. Начиная с Java 1.5 Java API предоставляет фреймворк Executor, который позволяет вам создавать различные пулы нитей, например single thread pool, который обрабатывает только одно задание за единицу времени, fixed thread pool, пул с фиксированным количеством нитей, и cached thread pool, расширяемый пул, подходящий для приложений с множеством недолгих заданий.
  49. Как решить Producer Consumer проблему?

  50. Большинство нитиевых проблем, которые вы решаете в реальности, из категории паттерна Producer Consumer, в котором одна нить порождает задачу, а вторая поглощает её. Вам нужно знать, Jak построить внутренние взаимодействия нитей, для решения этой проблемы. На низком уровне вы можете воспользоваться методами wait и notify, а на высоком уровне вы можете воспользоваться преимуществами Semaphore Lub BlockingQueue
  51. Как избежать взаимной блокировки (deadlock)?

  52. Tłumaczenie: 50 najpopularniejszych pytań do wywiadu według wątków.  Część 1. - 1 Deadlock – состояние, в котором нить ждёт, пока вторая нить совершит Jakое-либо действие, а вторая, в это же время, ждёт того же от первой. Это очень серьёзная проблема, из-за которой ваша программа зависает и не делает того, для чего она предназначена. Deadlock происходит, когда достигаются эти 4 состояния:
    • Взаимное исключение: по крайней мере один ресурс должен быть занят в режиме неделимости. Только один процесс может использовать ресурс в любой данный момент времени.
    • Удержание и ожидание: процесс удерживает Jak минимум один ресурс и запрашивает дополнительных ресурсов, которые удерживаются другими процессами.
    • Нет пред-очистке: операционная система не переназначивает ресурсы, если они уже заняты, они должны отдаваться удерживающим процессом добровольно.
    • Цикличное ожидание: процесс ждёт освобождения ресурсов другим процессом, который в свою очередь ждёт освобождения ресурсов первым процессом.
    Najprostszym sposobem uniknięcia zakleszczenia jest uniknięcie czekania w pętli; można to osiągnąć poprzez zdobywanie blokad w określonej kolejności i zwalnianie ich w odwrotnej kolejności.
  53. Różnice między blokadą na żywo a zakleszczeniem?

  54. Blokada na żywo jest podobna do zakleszczenia, z tą różnicą, że w przypadku blokady stany zaangażowanych wątków lub procesów stale się zmieniają w zależności od siebie. Livelock to szczególny przypadek niedoboru zasobów. Prawdziwym przykładem kłody jest sytuacja, gdy dwie osoby spotykają się w wąskim korytarzu i każda, starając się zachować uprzejmość, odsuwa się na bok i tak bez końca przechadzają się z boku na bok.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION