JavaRush /Java-Blog /Random-DE /Übersetzung: Top 50 Interviewfragen nach Thread. Teil 1.
KapChook
Level 19
Volga

Übersetzung: Top 50 Interviewfragen nach Thread. Teil 1.

Veröffentlicht in der Gruppe Random-DE
Der erste Teil der Übersetzung des Originalartikels „ Top 50 Java Thread Interview Questions Answers for Freshers, Experienced Programmers“. Zweiter Teil. Hinweis: Der Artikel ist groß geworden, weshalb er nicht in ein Thema passt. Außerdem ist es ziemlich kompliziert, ich habe mein Bestes versucht, es zu googeln, aber trotzdem. Deshalb bitten wir Teilnehmer, die fließend Englisch sprechen, einen Blick auf das Original zu werfen und es mit der Übersetzung zu vergleichen, falls sie etwas missverstanden oder falsch übersetzt haben. Vielen Dank im Voraus. In jedem Vorstellungsgespräch, ob Senior oder Junior, ob erfahren oder Anfänger, werden Sie mit einigen Fragen zu Threads, Parallelität und Multithreading konfrontiert. Tatsächlich ist diese integrierte Unterstützung für Parallelität eine der größten Stärken von Java und hat dazu beigetragen, dass Java bei Unternehmern und Programmierern gleichermaßen beliebt ist. Die meisten lukrativen Java-Entwicklerpositionen erfordern ausgezeichnete Multithreading-Kenntnisse und Erfahrung in der Entwicklung, dem Debuggen und Optimieren von Hochleistungsanwendungen mit geringer Latenz. Daher ist es eine der gefragtesten Fähigkeiten in Vorstellungsgesprächen. In einem typischen Java-Interview beginnt der Interviewer langsam mit den Grundkonzepten von Threads, stellt Fragen wie z. B. warum Threads benötigt werden, wie man sie erstellt, welche Art der Erstellung besser ist, von Thread erben oder Runnable implementieren, und bewegt sich dann langsam weiter Weiter zu den Schwierigkeiten der Parallelität, den Schwierigkeiten bei der Entwicklung paralleler Anwendungen, den in JDK 1.5 eingeführten Dienstprogrammen für die Parallelität auf hoher Ebene, den Prinzipien und Entwurfsmustern paralleler Anwendungen sowie den klassischen Multithreading-Problemen. Da es nicht ausreicht, nur die Grundlagen des Multithreadings zu kennen, müssen Sie wissen, wie Sie mit Parallelitätsproblemen wie Deadlock, Race Conditions, Speicherinkonsistenz und verschiedenen Thread-Sicherheitsproblemen umgehen. Diese Fähigkeiten werden gründlich getestet und stellen verschiedene Multithreading- und Parallelitätsherausforderungen dar. Viele Java-Entwickler lesen die Fragen normalerweise nur vor dem eigentlichen Interview, was keine schlechte Sache ist, aber Sie sollten dies verstehen. Außerdem verschwendet das Ansammeln von Fragen und das Durchführen der immer gleichen Übungen viel Zeit, deshalb habe ich diese Liste erstellt.
  1. Was ist ein Thread in Java?

  2. Ein Thread ist ein unabhängiger Ausführungspfad. Sein Ziel besteht darin, die Vorteile der mehreren in der Maschine verfügbaren Prozessoren zu nutzen. Durch die Verwendung mehrerer Threads können Sie CPU-gebundene Aufgaben beschleunigen. Wenn ein Thread beispielsweise 100 Millisekunden benötigt, um einen Job abzuschließen, können Sie 10 Threads verwenden, um diesen Job auf 10 Millisekunden zu reduzieren. Java bietet eine hervorragende Unterstützung für Multithreading auf Sprachebene und dies ist darüber hinaus einer seiner größten Vorteile.
  3. Unterschied zwischen Threads und Prozessen in Java?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  52. Übersetzung: Top 50 Interviewfragen nach Thread.  Teil 1. - 1 Deadlock – состояние, в котором нить ждёт, пока вторая нить совершит Wieое-либо действие, а вторая, в это же время, ждёт того же от первой. Это очень серьёзная проблема, из-за которой ваша программа зависает и не делает того, для чего она предназначена. Deadlock происходит, когда достигаются эти 4 состояния:
    • Взаимное исключение: по крайней мере один ресурс должен быть занят в режиме неделимости. Только один процесс может использовать ресурс в любой данный момент времени.
    • Удержание и ожидание: процесс удерживает Wie минимум один ресурс и запрашивает дополнительных ресурсов, которые удерживаются другими процессами.
    • Нет пред-очистке: операционная система не переназначивает ресурсы, если они уже заняты, они должны отдаваться удерживающим процессом добровольно.
    • Цикличное ожидание: процесс ждёт освобождения ресурсов другим процессом, который в свою очередь ждёт освобождения ресурсов первым процессом.
    Der einfachste Weg, Deadlocks zu vermeiden, besteht darin, das Warten in einer Schleife zu vermeiden. Dies kann erreicht werden, indem Sperren in einer bestimmten Reihenfolge erworben und in umgekehrter Reihenfolge freigegeben werden.
  53. Unterschiede zwischen Livelock und Deadlock?

  54. Ein Livelock ähnelt einem Deadlock, nur ändern sich bei einem Livelock die Zustände der beteiligten Threads oder Prozesse ständig voneinander. Livelock ist ein Sonderfall von Ressourcenknappheit. Ein echtes Beispiel für einen Livelock ist, wenn sich zwei Menschen in einem engen Korridor treffen und jeder, um höflich zu sein, zur Seite tritt und sich so endlos von einer Seite zur anderen bewegt.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION