[Java] Несколько вопросов для собеседования, которые позволят вам принять предложение

Java JVM HTTPS Безопасность

предисловие

Только лысина может стать сильнее

Когда я раньше просматривал блоги, я обнаружил, что некоторые хорошо написанные блоги будут автоматически собираться. В последнее время я проверяю утечки.Некоторые пункты знаний важнее, но они не были написаны в предыдущем блоге, поэтому я разберусь с ними, пока есть время.

Точки знания текста:

  • Целочисленный постоянный пул
  • Распаковка и вклейка TCP
  • select、poll、epollпростая разница
  • Синхронизированная оптимизация блокировки после jdk1.6
  • Модель памяти Java

эта статьяСтремитесь объяснить каждый пункт знаний просто, я надеюсь, что каждый сможет что-то получить после прочтения

1. Магическое целое

Некоторое время назад я увидел, как кто-то обсуждал в группе истинную или ложную проблему целых чисел, и я подумал, что понял пункты знаний в этом отношении. Но я все же ошибся, и тогда я пошел просить совета у друга. Друг прислал мне еще одну фотографию:

Позже я узнал, что это из раздела 10.3.2 в «Углубленном понимании виртуальной машины Java — расширенные функции и рекомендации JVM (второе издание)»~


public class Main_1 {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        System.out.println(c == d);
        System.out.println(e == f);
        System.out.println(c == (a + b));
        System.out.println(c.equals(a + b));
        System.out.println(g == (a + b));
        System.out.println(g.equals(a + b));
		System.out.println(g.equals(a + h));
    }

}

Вы можете сначала подумать об этом, а затем прокрутить вниз, чтобы увидеть, сможете ли вы сделать это правильно.

1.1 Идеи решения проблем

Прежде чем решить эту проблему, я полагаю, многие люди уже знают, что в Java будет целочисленный кэш-пул, и размер кэша:-128~127

ответ:

  • true
  • false
  • true
  • true
  • true
  • false
  • true

Кратко объясните:

  • использовать==Случай:
    • При сравнении целочисленных переменных сравнение по умолчаниюзначение адреса.
    • Целое число Java поддерживает-128~127буферный пул
    • Если одна сторона сравнения имеет операционное выражение (например, a+b), то сравнениеконкретное значение
  • использоватьequals()Случай:
    • Либо целое, либо длинноеequals()Сравнение по умолчаниюЧисленная величина.
    • Лонгаequals()метод, реализация JDK по умолчанию:Определит, является ли это типом Long
  • Обратите внимание на проблемы с автоматической распаковкой, автоматической упаковкой.

Декомпилируйте и посмотрите:


import java.io.PrintStream;

public class Main_1 {
    public static void main(String[] paramArrayOfString) {
        Integer localInteger1 = Integer.valueOf(1);
        Integer localInteger2 = Integer.valueOf(2);
        Integer localInteger3 = Integer.valueOf(3);
        Integer localInteger4 = Integer.valueOf(3);
        Integer localInteger5 = Integer.valueOf(321);
        Integer localInteger6 = Integer.valueOf(321);
        Long localLong = Long.valueOf(3L);

        // 缓存池
        System.out.println(localInteger3 == localInteger4);
        
        // 超出缓存池范围
        System.out.println(localInteger5 == localInteger6);
        
        // 存在a+b数值表达式,比较的是数值
        System.out.println(localInteger3.intValue() == localInteger1.intValue() + localInteger2.intValue());

        // equals比较的是数值
        System.out.println(localInteger3.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));
        // 存在a+b数值表达式,比较的是数值
        System.out.println(localLong.longValue() == localInteger1.intValue() + localInteger2.intValue());
        // Long的equals()先判断传递进来的是不是Long类型,而a+b自动装箱的是Integer类型
        System.out.println(localLong.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));

		// ... 最后一句在这里漏掉了,大家应该可以推断出来
    }
}

Инструмент декомпиляции, который я использую,jd-gui, если вы не пробовали декомпиляцию, можете скачать для игры:

2. Каковы методы оптимизации блокировки синхронизации?

Многопоточный обзор статьи:

Когда я раньше писал многопоточную статью, я вкратце сказал, что синхронизированные блокировки будут иметь различные оптимизации после jdk1.6: адаптивные спин-блокировки, устранение блокировок, огрубление блокировок, облегченные блокировки и предвзятые блокировки.

Я думал, что эти оптимизации очень сложны для понимания, но это не так, они все еще очень просты для понимания.

2.1 Адаптация спин-блокировок

Соревнование блокировки находится в режиме ядра и будет проходить через пользовательский режим (режим пользователя) в режим ядра (режим ядра).переключать, занимает больше времени.

блокировка спинаПричина в том, что люди находят, что большую часть времениЗанятость замка продлится только на короткое время, даже меньше, чем время, необходимое для переключения в режим ядра, поэтому пусть поток ждет в течение ограниченного времени, прежде чем войти в режим ядра, если блокировка может быть получена в течение этого времени.Избегайте большого количества бесполезного времени, если нет, то войдите в режим ядра, чтобы побороться за блокировку.

Адаптивные спин-блокировки были представлены в JDK 1.6, заявивВремя вращения не фиксировано, вы хотите, чтобы вращение становилось все умнее и умнее?.

Спин-блокировка была введена в JDK1.4.2, но по умолчанию она закрыта и ее можно использовать.-XX:+UseSpinningпараметр для открытия, в JDK1.6 был изменен надефолтвключенный.

Использованная литература:

  • Каковы применимые сценарии для спин-блокировок и не-спин-блокировок, которые переводят потоки в спящий режим?Ууху. Call.com/question/38…

2.2 Устранение блокировки

Если JVM явно обнаруживает, что определенный фрагмент кодапотокобезопасность(подразумевается: никакая блокировка также небезопасна), JVM безопасно устранит исходную блокировку!

Например:


    public void vectorTest(){
        Vector<String> vector = new Vector<String>();
        for(int i = 0 ; i < 10 ; i++){
            vector.add(i + "");
        }

        System.out.println(vector);
    }

Вектор заблокирован по умолчанию, но если JVM обнаружит, что векторная переменная заблокирована только вvectorTest()метод, вектор является потокобезопасным. JVM удалит блокировку, добавленную внутри вектора, и эта оптимизация называется устранением блокировки.

2.3 Огрубление блокировки

По умолчанию всегда рекомендуетсяОбъем синхронизированного блока ограничен как можно меньшим.

Но если серия последовательных операций вернаМногократная блокировка и разблокировка одного и того же объекта, даже если операция блокировки происходит в теле цикла, частые взаимоисключающие операции синхронизации также приведут кненужный штраф за производительность.

JVM заблокирует диапазонрасширять(огрубление), это называется огрублением замков.

2.4 Легкий замок

Основанием для того, что упрощенные блокировки могут улучшить производительность синхронизации программ, является «для большинства блокировок нет конкуренции во всем цикле синхронизации», что является эмпирическими данными.

  • Если нет конфликта, легкие замки используютсяОперации CAS избегают накладных расходов с использованием Mutexes
  • Но при наличии конкуренции блокировок помимо накладных расходов на мьютекс возникает дополнительная операция CAS, поэтому в случае конкуренции облегченные блокировки будут медленнее, чем традиционные тяжеловесные блокировки.

Проще говоря: если установлено, что период синхронизациинет конкуренции, JVM будет использоватьОперация CAS для замены мьютекса ОС. Эта оптимизация называется облегченной блокировкой.

2.5 Блокировка смещения

Блокировка смещения включенаВ случае отсутствия конкуренции вся синхронизация исключается, и даже операция CAS не выполняется.!

Блокировку смещения можно улучшитьПроизводительность программы с синхронизацией, но без конкуренции. Это также оптимизация с характером компромисса (Trade Off), то есть она не всегда выгодна для работающей программы, если к большинству блокировок в программе всегда обращаются несколько разных потоков, она необъективна. Шаблоны избыточны. На основе конкретного анализа конкретных проблем иногда используются параметры-XX:-UseBiasedLockingВместо этого отключение предвзятой блокировки может повысить производительность.

2.6 Краткий обзор различных оптимизаций блокировок

  • Адаптивная блокировка смещения: нефиксированное время отжима
  • Снятие блокировки: снимите блокировку, если код признан потокобезопасным.
  • Огрубление блокировки: диапазон блокировки слишком мал (повторяющаяся блокировка), а диапазон блокировки расширен.
  • Легкие замки: при отсутствии разногласийИспользуйте операции CAS для устранения мьютексов, используемых при синхронизации
  • Предвзятая блокировка: В неконкурентной среде вся синхронизация исключается, и CAS этого не делает.

Использованная литература:

Три, липкий пакет ПТС, распаковка

Это вопрос из интервью, который я увидел, когда наблюдал за боссом Ванцзинсинь. Раньше у меня не было понятия о приклеивании и распаковке TCP, поэтому я просто пошел, чтобы понять это.

3.1 Что такое распаковка и вклейка? Почему оно появляется?

При изучении Java NIO,возможныйНайдет: если клиентнепрерывноПри отправке пакетов данных на сервер данные, полученные сервером, будут отображаться в двух пакетах.придерживатьсявместе.

Формат заголовка TCP:

  • TCP этопоток байтов на основе, хотя взаимодействие данных между прикладным уровнем и транспортным уровнем TCP представляет собой блоки данных разного размера, но TCP рассматривает эти блоки данных только как серию неструктурированных потоков байтов,нет границ;
  • Из структуры кадра TCP также видно, что в заголовке TCPНет поля для длины данных

Исходя из двух вышеперечисленных моментов, при использовании TCP для передачи данных есть вероятность залипания или распаковки.

Пакет данных содержит информацию о двух пакетах данных, отправленных отправителем., это явление называется прилипанием

Получатель получает два пакета, но два пакетаЛибо он неполный, либо это лишний кусок, в этом случае происходит распаковка и залипание

Проблемы с распаковкой и склеиванием, вызванныеПолучатель обрабатываетбудет очень сложно (потому что нет возможности отличитьполныйпакет данных)

3.2 Решение распаковки и наклеивания

Как правило, существует два механизма субподряда.Универсальныйобходной путь:

  • 1, управление специальными символами
  • 2, добавьте длину пакета данных в заглавную часть заголовка пакета

Если используете netty, то есть специальные энкодеры и декодеры для решения проблемы распаковки и втыкания.

tips:UDP не имеет проблемы с липкими пакетами, но с потерей пакетов и выходом из строя. Неполных пакетов не будет, будут получены только правильные пакеты. Протокол блока передаваемых данных представляет собой UDP-пакет или пользовательскую дейтаграмму, которая не объединяется и не разделяется при отправке.

использованная литература

Четыре, выберите, опрос, epoll простая разница

Обзор НИО:

Под Linux он реализует модель мультиплексирования ввода-вывода следующим образом:

перечислитьselect/poll/epollОдна из функций, передавая несколько файловых дескрипторов, возвращает значение, если один из них готов, в противном случае блокируется до истечения времени ожидания.

Эти функции несколько отличаются, и некоторые интервьюеры могут спросить, в чем разница между этими тремя функциями:

Разница заключается в следующем:

Резюме из двух предложений:

  • select和pollоба должны опрашивать каждый файловый дескриптор,epollНа основе событий, без опроса
  • select和pollКаждый раз, когда вам нужно скопировать дескриптор файла,epollНе нужно
  • selectМаксимальное количество подключений ограничено,epoll和pollНеограниченное максимальное количество подключений

советы: реализация epoll в ядре, использование красно-черного дерева для управления блоками событий

4.1 Популярный пример

Сейчас 3y — стажер в компании, и написанный код нужно еще раз протестировать.

select/pollсостояние:

  • Разработка — это написание кода, тестирование в это времяспрашивай один за другимВсе разработчики, вы уже написали программу? Хотите протестировать?

epollсостояние:

  • После того, как разработка закончила писать код, скажите тестировщику: «Я написал код, вы идете тестировать, функция XXX». Так что тестер с радостью отправился искать баги.

Другие популярные описания [1]:

Бармен (нить), перед ним лежит группа пьяных, вдруг один орёт "Налей вина" (событие), ты подбегаешь и наливаешь ему выпивку, потом отпускаешь, вдруг другой хочет налить вина , ты опять В прошлом был такой официант обслуживал много людей и иногда никто не пил.Официант был в бездействующем состоянии и мог заниматься чем-то другим и играть со своим мобильным телефоном. Что касается epoll и select, то разница между poll в том, что в последних двух сценах пьяный мужчина не разговаривает, вы должны спрашивать один за другим, хотите ли вы алкоголь, и у вас нет времени играть с телефоном. . io мультиплексирование, вероятно, означает, что эти пьяницы делят официанта.

источник:

Другие популярные описания [2]:

Приведем простой пример (может быть не очень наглядный): select/poll официант ресторана (ядро) говорит владельцу ресторана (пользовательской программе): «Теперь есть гости на выписку», но никто из официантов внятно не сказал боссу, какой столы гостей, чтобы проверить. Босс должен спрашивать каждый стол один за другим: Извините, вы хотите оплатить счет? Официант (ядро) отеля epoll сообщает владельцу отеля (пользовательская программа): «Гости 1, 2 и 5 выписались», и босс может перейти прямо к столикам 1, 2 и 5, чтобы собрать деньги.

источник:

Подробнее о ссылках:

5. Модель памяти Java

Обзор сообщения в блоге JVM:

Когда я раньше писал JVM, я однажды поместилСтруктура памяти JVM и модель памяти JavaЯ запутался~~~ К счастью, некоторые восторженные пользователи сети указали мне на это.

Структура памяти JVM:

Модель памяти Java:

Правила при работе с переменными:

  • Модель памяти Java определяет всепеременные хранятся в основной памяти
  • резьбовойрабочая памятьОсновная память, в которой хранятся переменные, используемые потокомкопировать копировать
  • все потоки имеют переменнуюдействовать(чтения, задания и т. д.) должны бытьрабочая память, вместо прямого чтения и записи переменных в основную память

отРабочая память синхронизируется с основной памятьюРеализация осуществляется посредством следующих 8 операций:

  • lock: переменная, которая воздействует на основную память и идентифицирует переменную как эксклюзивную для потока.
  • Unlock (разблокировать): Воздействует на переменную основной памяти, чтобы освободить переменную в заблокированном состоянии, и освобожденная переменная может быть заблокирована другими потоками.
  • чтение (чтение): воздействует на переменную основной памяти и передает значение переменной из основной памяти в рабочую память потока для использования в последующих действиях загрузки
  • load: переменная, действующая на рабочую память, которая помещает значение переменной, полученное операцией чтения из основной памяти, в копию переменной в рабочей памяти.
  • использование: переменная, воздействующая на рабочую память, передавая значение переменной в рабочей памяти механизму выполнения, который будет выполняться всякий раз, когда виртуальная машина встречает инструкцию байт-кода, которая должна использовать значение переменной.
  • assign (назначение): переменная, воздействующая на рабочую память, она присваивает значение, полученное от исполнительного механизма, переменной в рабочей памяти, и выполняет эту операцию всякий раз, когда виртуальная машина встречает инструкцию байт-кода, которая присваивает значение переменной.
  • store (хранилище): переменная, действующая на рабочую память, передающая значение переменной из рабочей памяти в основную память для последующих операций записи.
  • запись: переменная, которая воздействует на основную память и передает операцию сохранения из значения переменной в рабочей памяти в переменную в основной памяти.

Модель памяти Java построена вокруг параллельных процессов.Как справиться с атомарностью, видимостью и упорядоченностьюЭти 3 характеристики создаются

Операции гарантированно атомарны:

  • read、load、assign、use、store和write
  • СИНХРОНИЗИРОВАННЫЙ замок

Операции, гарантирующие упорядочение (переупорядочение вызывает неупорядочение):

  • volatile
  • синхронизированный замок

Гарантированная видимость:

  • volatile
  • синхронизированный замок
  • final

Как упоминалось выше, упорядоченность может быть гарантирована изменчивыми и синхронизированными блокировками, но когда мы обычно пишем программыНе всегда заботится о порядке кодаиз. На самом деле внутри Java у нас есть принцип, который называетсяпроисходит до принципа(happens-before)

  • Можно принять принцип «происходит до»: несколькоправилоПакет для решения проблемы между двумя операциями в параллельной среде.Возможен ли конфликтвсе вопросы
  • С этими правилами и нашимиДействия находятся в рамках, определенных этими правилами. Мы можем гарантировать, что операция A должна произойти до операции B (проблем с переупорядочением не возникнет).

Принцип «происходит до» включает в себя следующее:

  • Правило порядка программы: внутри потока, в соответствии с порядком программного кода, операции, написанные в начале, выполняются до операций, записанных в конце. Чтобы быть точным, это должен быть порядок потока управления, а не порядок кода программы, потому что учитываются такие структуры, как ветви, циклы и т. д.
  • Правило блокировки монитора: сначала выполняется операция разблокировки перед последующей операцией блокировки той же блокировки. Здесь следует подчеркнуть тот же замок, а «позже» относится к порядку во времени.
  • Правило для изменчивых переменных: операция записи в изменчивую переменную происходит раньше, чем операция чтения переменной.«Позднее» здесь также относится к последовательности во времени. Правило запуска потока: метод start() объекта Thread предшествует каждому действию этого потока.
  • Правило завершения потока: все операции в потоке выполняются первыми при обнаружении завершения этого потока.Мы можем определить, что поток был завершен по окончании метода Thread.join() и возвращаемому значению Thread.isAlive(). Прекратить выполнение.
  • Правило прерывания потока: вызов метода прерывания() потока происходит первым, когда код прерванного потока обнаруживает возникновение события прерывания и может определить наличие прерывания с помощью метода Thread.interrupted().
  • Правило финализатора: завершение инициализации объекта (конец выполнения конструктора) происходит сначала в начале его метода finalize().
  • Транзитивность: если операция A происходит раньше операции B, а операция B происходит раньше операции C, то можно сделать вывод, что операция A происходит раньше операции C.

Использованная литература:

6. Наконец

В этой статье кратко систематизированы заметки, сделанные во время исследования, а также некоторые более важные сведения (вопросы для интервью), найденные в Интернете. Надеюсь, вам будет полезно ее прочитать.

Использованная литература:

  • «Глубокое понимание виртуальной машины Java — расширенные функции и рекомендации JVM (2-е издание)»

Если у вас есть лучший способ понять или в статье есть ошибки, пожалуйста, не стесняйтесь оставлять сообщение в области комментариев, чтобы мы могли учиться друг у друга~~~

Если вы хотите увидеть большеоригинальныйТехнические статьи, приглашаю всех обратить на меня вниманиеПубличный аккаунт WeChat: Java3y. Также есть публичные аккаунтыОгромные видеоресурсыО, следуйте, чтобы получить его бесплатно.

Ссылки, которые могут представлять интерес: