Последние вопросы и ответы на собеседованиях по Java в 2018 году

Java

оригинал:Ссылка на сайт

Следующие вопросы интервью были собраны в Интернете. Я нашел эталонный ответ с отношением к обучению. Пожалуйста, поправьте меня, если есть какие-либо недостатки. Для получения более интересного контента вы можете обратить внимание на мой публичный аккаунт WeChat: Java Head

Основы

основные навыки

Объектно-ориентированные функции

Инкапсуляция, наследование, полиморфизм и абстракция

  1. упаковка
    Инкапсуляция предоставляет объектам возможность скрывать внутренние функции и поведение. Объекты предоставляют методы, к которым другие объекты могут получить доступ для изменения
    изменить свои внутренние данные. В Java есть 3 модификатора: public, private и protected. каждый модификатор
    Разные права доступа предоставляются другим объектам, расположенным в том же пакете или в разных пакетах.
    Некоторые из преимуществ использования инкапсуляции перечислены ниже:

    1.通过隐藏对象的属性来保护对象内部的状态。
    2.提高了代码的可用性和可维护性,因为对象的行为可以被单独的改变或者是扩展。
    3.禁止对象之间的不良交互提高模块化
    
  2. наследовать
    Наследование предоставляет объектам возможность получать поля и методы из базовых классов. Наследование предоставляет многократно используемые строки кода, а также можно добавлять новые функции к существующим классам без изменения класса.

  3. полиморфизм
    Полиморфизм — это способность языка программирования представлять один и тот же интерфейс для различных базовых типов данных. Операции над полиморфным типом можно применять к значениям других типов.

  4. Аннотация
    Абстракция — это этап отделения идей от конкретных экземпляров, поэтому классы создаются на основе их функциональности, а не деталей реализации. Java поддерживает создание абстрактных классов, которые предоставляют только интерфейсы, но не реализации методов. Основная цель этого метода абстракции — отделить поведение класса от деталей реализации.

Разница между final, finalize, finalize

  1. final
    Модификатор (ключевое слово) Если класс объявлен окончательным, это означает, что он не может быть получен из новых подклассов и не может быть унаследован как родительский класс. Поэтому класс не может быть объявлен одновременно абстрактным и окончательным. Объявление переменных или методов final гарантирует, что они не будут изменены во время использования. Переменной, объявленной как final, должно быть присвоено начальное значение во время объявления, и она может быть только прочитана, но не изменена при последующих ссылках. Методы, объявленные как final, можно только использовать и нельзя перегружать.

  2. finally
    Предоставьте блок finally для выполнения любой очистки при обработке исключений. Если возникает исключение, выполняется соответствующее предложение catch, и управление переходит к блоку finally (если он есть).

  3. finalize
    имя метода. Технология Java позволяет использовать метод finalize() для выполнения необходимой очистки перед тем, как сборщик мусора удалит объект из памяти. Этот метод вызывается сборщиком мусора для этого объекта, когда он определяет, что на объект нет ссылки. Он определен в классе Object, поэтому все классы наследуются от него. Подклассы переопределяют метод finalize() для очистки системных ресурсов или выполнения другой работы по очистке. Метод finalize() вызывается для объекта до того, как сборщик мусора удалит его.

В чем разница между int и Integer

int — примитивный тип данных
Integer — это его класс-оболочка, обратите внимание, что это класс.
Зачем предоставлять класс-оболочку? ? ?
Одним из них является преобразование между различными типами посредством вызова различных методов. В противном случае вы не сможете конвертировать напрямую через переменные.
Например, теперь int нужно преобразовать в String

  1. int a=0;
  2. String result=Integer.toString(a);
скопировать код

Классы упаковки в java в основном используются при преобразовании различных типов данных.
Я пишу несколько демо
// Реализовать преобразование через класс-оболочку

  1. int num=Integer.valueOf("12");
  2. int num2=Integer.parseInt("12");
  3. double num3=Double.valueOf("12.2");
  4. double num4=Double.parseDouble("12.2");
  5. //其他的类似。通过基本数据类型的包装来的valueOf和parseXX来实现String转为XX
  6. String a=String.valueOf("1234");//这里括号中几乎可以是任何类型
  7. String b=String.valueOf(true);
  8. String c=new Integer(12).toString();//通过包装类的toString()也可以
  9. String d=new Double(2.3).toString();
скопировать код

Другой пример. Например, я сейчас использую дженерики

  1. List<Integer> nums;
скопировать код

Здесь требуется класс. если вы используете внутр. Он сообщит об ошибке.

Разница между перегрузкой и переопределением

отменить

1. Имя метода, параметры и возвращаемое значение совпадают.

2. Методы подкласса не могут сузить права доступа методов суперкласса.

3. Методы подкласса не могут генерировать больше исключений, чем методы суперкласса (но методы подкласса не могут генерировать исключений).

4. Существует между родительским и дочерним классами.

5. Метод определен как окончательный и не может быть переопределен.

перегрузка

1. По крайней мере один тип параметра, номер и порядок отличаются.

2. Нельзя перегружать имена методов, которые имеют только разные возвращаемые значения.

3. Существовать в родительском и дочернем классах и в одном классе.

В чем разница между абстрактным классом и интерфейсом

Интерфейс является общедоступным и не может иметь в себе приватных методов или переменных, он используется другими, в то время как абстрактные классы могут иметь приватные методы или приватные переменные.
Кроме того, те, кто реализует интерфейс, должны реализовать все методы, определенные в интерфейсе, а абстрактный класс реализации может выборочно переопределять методы, которые необходимо использовать.В общих приложениях верхний уровень — это интерфейс, затем абстрактный класс реализует интерфейс и, наконец, пока конкретный класс не будет реализован.
Также интерфейсы могут реализовывать множественное наследование, а класс может наследовать только один суперкласс, но множественное наследование может быть достигнуто путем наследования нескольких интерфейсов.Интерфейс также имеет идентичность (в нем нет метода, такого как интерфейс Remote) и данные совместное использование (внутри интерфейса).все переменные являются константами).

Расскажите об использовании и реализации отражения

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

Основные возможности отражения Java:

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

Существует много приложений отражения, и используется множество фреймворков.

Весенний ioc/di также является отражением....
Вызов между javaBean и jsp также является отражением....
Между FormBean распорок и страницей... также вызываемой отражением....
classForName() JDBC также является отражением.....
находка спящего режима (класс clazz) также является отражением....

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

источник:UU.ITeye.com/blog/142351…

Расскажите о сцене и реализации пользовательских аннотаций

(Этот вопрос можно задать бесплатно, все зависит от вашего понимания аннотаций! ==) Вход в систему, перехват разрешений, обработка логов и различные Java-фреймворки, такие как Spring, Hibernate, JUnit Когда дело доходит до аннотаций, вы ничем не можете помочь но поговорим об отражении, настройке Java. Аннотации получаются путем отражения во время выполнения. В реальной разработке, например, если мы хотим получить журнал вызовов метода, мы можем добавить аспекты к методу через АОП (механизм динамического прокси) и получить аннотации, содержащиеся в методе, посредством отражения.Если аннотации журнала включены , выполняется запись журнала.

Разница между GET и POST для HTTP-запросов

Метод GET добавляет пары «имя-значение» к запрошенному URL-адресу. Поскольку URL-адреса имеют ограничение на количество символов, что, в свою очередь, ограничивает количество значений параметров, используемых в клиентских запросах. А значения параметров в запросе видны, следовательно, конфиденциальная информация не может быть передана таким образом.

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

Ссылаться на:Блог Woohoo.cn on.com/Wang Li-66/Afraid…

Разница между сеансом и файлом cookie

Файл cookie — это часть информации, которую веб-сервер отправляет в браузер. Браузер будет обслуживать каждую веб-службу в локальном файле.
Устройство сохраняет файлы cookie. В будущем, когда браузер отправит запрос на определенный веб-сервер, он также будет отправлять все запросы для этого сервера.
файлы cookie, хранящиеся на сервере. Разница между сеансом и файлом cookie указана ниже:
Сеансы должны работать независимо от настроек браузера клиента. Клиенты могут отключить файлы cookie,
Однако сеанс все еще работает, поскольку клиент не может отключить сеанс сервера.

JDBC-процесс

1. Загрузите драйвер JDBC:
Перед подключением к базе данных сначала загрузите драйвер базы данных, которую вы хотите подключить к JVM (виртуальная машина Java),
Это достигается с помощью статического метода forName(String className) класса java.lang.Class.
Например:

  1. try{
  2. //加载MySql的驱动类
  3. Class.forName("com.mysql.jdbc.Driver") ;
  4. }catch(ClassNotFoundException e){
  5. System.out.println("找不到驱动程序类 ,加载驱动失败!");
  6. e.printStackTrace() ;
  7. }
скопировать код

После успешной загрузки экземпляр класса Driver регистрируется в классе DriverManager.

2. Укажите URL-адрес соединения JDBC.

  • URL-адрес подключения определяет протокол, подпротокол и идентификатор источника данных при подключении к базе данных.
  • Форма записи: Протокол: Подпротокол: Идентификация источника данных

Протокол: всегда начинается с jdbc в JDBC. Подпротокол: это имя драйвера мостового соединения или системы управления базой данных.
Идентификация источника данных: отметьте адрес и порт подключения, где находится источник базы данных.
Например:
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk;useUnicode=true; (URL-адрес подключения MySql)
Указывает на использование набора символов Unicode. Этот параметр должен иметь значение true, если для параметра characterEncoding установлено значение gb2312 или GBK. characterEncoding=gbk: метод кодирования символов.

3. Создайте подключение к базе данных

  • Чтобы подключиться к базе данных, вам необходимо запросить и получить объект Connection из java.sql.DriverManager, который представляет собой подключение к базе данных.
  • Используйте метод getConnectin(String url, String username, String password) DriverManager, чтобы передать указанный путь к базе данных для подключения, имя пользователя и пароль для получения базы данных.

Например: // Подключиться к базе данных MySql, и имя пользователя, и пароль — root

  1. String url = "jdbc:mysql://localhost:3306/test" ;
  2. String username = "root" ;
  3. String password = "root" ;
  4. try{
  5. Connection con = DriverManager.getConnection(url , username , password ) ;
  6. }catch(SQLException se){
  7. System.out.println("数据库连接失败!");
  8. se.printStackTrace() ;
  9. }
скопировать код

4. Создайте заявление
• Чтобы выполнить оператор SQL, вы должны получить экземпляр java.sql.Statement, который делится на следующие три типа:
1. Выполните статические операторы SQL. Обычно реализуется через экземпляр Statement.
2. Выполните динамические операторы SQL. Обычно реализуется через экземпляр PreparedStatement.
3. Выполните хранимую процедуру базы данных. Обычно реализуется через экземпляр CallableStatement.
Конкретный метод реализации:
Заявление stmt = con.createStatement() ;
5. Выполните оператор SQL
Интерфейс Statement предоставляет три метода для выполнения операторов SQL: executeQuery, executeUpdate и execute.
1. ResultSet executeQuery(String sqlString): выполнение оператора SQL для запроса к базе данных и возврата объекта набора результатов (ResultSet).
2. int executeUpdate(String sqlString): используется для выполнения операторов INSERT, UPDATE или DELETE и операторов SQL DDL, таких как: CREATE TABLE и DROP TABLE и т. д.
3. execute(sqlString): используется для выполнения инструкции, которая возвращает несколько наборов результатов, несколько счетчиков обновлений или их комбинацию. Конкретный код реализации:
ResultSet rs = stmt.executeQuery("SELECT * FROM...") int rows = stmt.executeUpdate("INSERT INTO...") логический флаг = stmt.execute(String sql) ;
6. Обработка результатов
Два случая:
1. Выполнение обновления возвращает количество записей, затронутых этой операцией.
2. Результат, возвращаемый выполнением запроса, является объектом ResultSet.
• ResultSet содержит все строки, удовлетворяющие условиям оператора SQL, и обеспечивает доступ к данным в этих строках с помощью набора методов получения.
• Используйте методы доступа объекта ResultSet для получения данных:
while(rs.next()){
Имя строки = rs.getString ("имя");
String pass = rs.getString(1) ;// Этот метод более эффективен
}
(столбцы нумеруются слева направо и начинаются со столбца 1)

7. Закройте объект JDBC.
После завершения операции все используемые объекты JDBC должны быть закрыты для высвобождения ресурсов JDBC, порядок закрытия противоположен порядку объявления:
1. Закройте набор записей
2. Заключительное заявление
3. Закройте объект соединения

  1. if(rs != null){ // 关闭记录集
  2. try{
  3. rs.close() ;
  4. }catch(SQLException e){
  5. e.printStackTrace() ;
  6. }
  7. }
  8. if(stmt != null){ // 关闭声明
  9. try{
  10. stmt.close() ;
  11. }catch(SQLException e){
  12. e.printStackTrace() ;
  13. }
  14. }
  15. if(conn != null){ // 关闭连接对象
  16. try{
  17. conn.close() ;
  18. }catch(SQLException e){
  19. e.printStackTrace() ;
  20. }
  21. }
скопировать код

Дизайнерское мышление MVC

MVC это
М: Модель модели
V: Просмотр просмотра
C: контроллер контроллера
Модель представляет собой модуль, который инкапсулирует бизнес-логику и данные, а контроллер должен вызывать эти модули (обычно реализуемые сервлетом в java, и многие фреймворки используют Struts2 для реализации этого уровня), представление в основном то, что вы видите, например как JSP и т. д.
Когда пользователь отправляет запрос, контроллер выбирает бизнес-логику для обработки и данные, которые должны быть выбраны в соответствии с запросом, а затем возвращается для вывода результата на уровень представления, что может быть перенаправлением или пересылкой.

Разница между равными и ==

Типы значений (int, char, long, boolean и т. д.) используют == для определения равенства. Для ссылок на объекты == определяет, являются ли объекты, на которые ссылается ссылка, одинаковыми. equals является функцией-членом Object.Некоторые классы переопределяют этот метод для определения эквивалентности объектов. Например, в классе String обе строки, на которые указывают две ссылки, имеют значение «abc», но на самом деле они могут не соответствовать одному и тому же объекту (связанному с реализацией jvm), поэтому используйте ==, чтобы судить о том, что они не могут быть равным, но использовать равные Суждения должны быть равными.

собирать

Разница между списком и набором

List, Set наследуются от интерфейса Collection

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

Особенности набора: элементы расположены не по порядку, элементы не могут повторяться, а повторяющиеся элементы будут перезаписаны.

(Примечание. Хотя элементы расположены не по порядку, положение элемента в наборе определяется HashCode элемента, и его положение фактически фиксировано. Объект, добавляемый в набор, должен определять метод equals(). Кроме того, список поддерживает циклы for, то есть для обхода по нижнему индексу можно также использовать итератор, но set может использовать только итерацию, потому что это не по порядку, вы не можете использовать нижний индекс для получения нужного значения.)

Сравнение набора и списка:

Установить: эффективность извлечения элементов низкая, а эффективность удаления и вставки высока. Вставка и удаление не вызовут изменения положения элемента.

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

Разница между списком и картой

Список — это набор объектов, позволяющий повторять объекты.

Карта представляет собой набор пар ключ-значение и не допускает дублирования ключей.

Разница между Arraylist и LinkedList

Список массивов:

Преимущества: ArrayList реализует структуру данных на основе динамических массивов.Поскольку адреса непрерывны, после сохранения данных эффективность работы запроса будет относительно высокой (он подключается в памяти).

Недостатки: Поскольку адреса непрерывны, ArrayList необходимо перемещать данные, поэтому эффективность операций вставки и удаления относительно низка.

Связанный список:

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

Недостатки: поскольку LinkedList необходимо перемещать указатель, производительность операции запроса относительно низкая.

Применимый анализ сценариев:

Используйте ArrayList, когда вам нужно получить доступ к данным, и используйте LinkedList, когда вам нужно добавлять, удалять и изменять данные несколько раз.

Разница между ArrayList и Vector

  1. public ArrayList(int initialCapacity)//构造一个具有指定初始容量的空列表。
  2. public ArrayList()//构造一个初始容量为10的空列表。
  3. public ArrayList(Collection<? extends E> c)//构造一个包含指定 collection 的元素的列表
скопировать код

Вектор имеет четыре конструктора:

  1. public Vector()//使用指定的初始容量和等于零的容量增量构造一个空向量。
  2. public Vector(int initialCapacity)//构造一个空向量,使其内部数据数组的大小,其标准容量增量为零。
  3. public Vector(Collection<? extends E> c)//构造一个包含指定 collection 中的元素的向量
  4. public Vector(int initialCapacity,int capacityIncrement)//使用指定的初始容量和容量增量构造一个空的向量
скопировать код

И ArrayList, и Vector реализованы с помощью массивов, и есть три основных отличия:

  1. Vector безопасен для многопоточности.Безопасность потоков означает, что несколько потоков обращаются к одному и тому же коду без получения неопределенных результатов. ArrayList не является, это видно из исходного кода, многие методы в классе Vector модифицированы с помощью synchronized, что делает Vector не в состоянии сравниться с ArrayList по эффективности;

  2. Оба используют линейное непрерывное пространство для хранения элементов, но когда места недостаточно, два класса добавляются по-разному.

  3. Vector может установить коэффициент роста, а ArrayList — нет.

  4. Vector — это старый динамический массив, синхронизированный с потоками и неэффективный, поэтому он обычно устарел.

Применимый анализ сценариев:

  1. Vector синхронен с потоком, поэтому он также безопасен для потоков, в то время как ArrayList является асинхронным потоком и небезопасен. Если фактор безопасности потока не учитывается, обычно использование ArrayList более эффективно.

  2. Если количество элементов в коллекции превышает длину массива текущей коллекции, использование большого объема данных в коллекции имеет определенные преимущества.

Разница между HashMap и Hashtable

1. HashMap удаляет метод contains из HashTable, но добавляет методы containsValue() и containsKey().

2. HashTable синхронная, а HashMap асинхронная, поэтому эффективность выше, чем у hashTable.

3.HashMap допускает нулевые значения ключа, а hashTable — нет.

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

Карта дерева: подходит для обхода ключей в естественном или пользовательском порядке.

Ссылаться на:blog.CSDN.net/QQ_22118507…

Разница между HashSet и HashMap

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

map — это карта пар ключ-значение, которые могут быть нулевыми и нулевыми. HashMap — это хеш-реализация интерфейса Map.Уникальность ключа определяется уникальностью хеш-значения значения ключа, а значение-значение представляет собой структуру связанного списка.

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

Разница между HashMap и ConcurrentHashMap

ConcurrentHashMap — это поточно-ориентированная реализация HashMap.

(1) ConcurrentHashMap делит весь массив бакетов на сегменты, а затем защищает каждый сегмент блокировками блокировки. По сравнению с блокировкой ключевого слова syn в HashTable точность детализации и производительность параллелизма лучше. , в то время как HashMap не имеет механизма блокировки и не является потоком. -безопасно.

(2) Пара ключ-значение HashMap может иметь значение null, но ConCurrentHashMap не допускает этого.

Принцип работы и кодовая реализация HashMap

Ссылаться на:Трейси игнорирует.GitHub.IO/2015/07/01/…Изучение коллекции 1: принцип реализации HashMap/

Принцип работы и кодовая реализация ConcurrentHashMap

В HashTable используется ключевое слово synchronized, которое фактически блокирует объект, а блокируется весь объект, когда размер Hashtable увеличивается до определенного уровня, производительность резко падает, потому что его нужно блокировать на долгое время. во время итерации.

ConcurrentHashMap — это оптимизация вышеуказанных проблем, его конструктор выглядит следующим образом, а значения по умолчанию — 16, 0,75 и 16.

  1. public ConcurrentHashMap(int paramInt1, float paramFloat, int paramInt2) {
  2. //…
  3. int i = 0;
  4. int j = 1;
  5. while (j < paramInt2) {
  6. ++i;
  7. j <<= 1;
  8. }
  9. this.segmentShift = (32 - i);
  10. this.segmentMask = (j - 1);
  11. this.segments = Segment.newArray(j);
  12. //…
  13. int k = paramInt1 / j;
  14. if (k * j < paramInt1)
  15. ++k;
  16. int l = 1;
  17. while (l < k)
  18. l <<= 1;
  19. for (int i1 = 0; i1 < this.segments.length; ++i1)
  20. this.segments[i1] = new Segment(l, paramFloat);
  21. }
  22. public V put(K paramK, V paramV) {
  23. if (paramV == null)
  24. throw new NullPointerException();
  25. int i = hash(paramK.hashCode()); //这里的hash函数和HashMap中的不一样
  26. return this.segments[(i >>> this.segmentShift & this.segmentMask)].put(paramK, i, paramV, false);
  27. }
скопировать код

ConcurrentHashMap вводит сегментацию.Последняя строка в приведенном выше коде на самом деле может быть понята как разбиение большой карты на N маленьких HashTables.В методе put это будет определяться в соответствии с хэшем(paramK.hashCode()) Какой сегмент хранится в, если мы посмотрим на операцию размещения сегмента, мы обнаружим, что внутренний механизм синхронизации основан на операции блокировки, так что часть карты (сегмент) может быть заблокирована, что влияет только на тот же сегмент. put работа элементов Segment гарантированно синхронизирована, вся Map не блокируется (это делает HashTable).По сравнению с HashTable улучшена производительность в многопоточной среде, поэтому HashTable исключен.

нить

Как создать поток и его реализация

Существует три основных способа создания потоков в Java:

Во-первых, наследуйте класс Thread, чтобы создать класс потока.

(1) Определить подкласс класса Thread и переписать метод запуска класса.Тело метода метода запуска представляет задачу, которую должен выполнить поток. Поэтому метод run() называется исполнителем.

(2) Создайте экземпляр подкласса Thread, то есть создайте объект потока.

(3) Вызовите метод start() объекта потока, чтобы запустить поток.

  1. package com.thread;
  2. public class FirstThreadTest extends Thread{
  3. int i = 0;
  4. //重写run方法,run方法的方法体就是现场执行体
  5. public void run()
  6. {
  7. for(;i<100;i++){
  8. System.out.println(getName()+" "+i);
  9. }
  10. }
  11. public static void main(String[] args)
  12. {
  13. for(int i = 0;i< 100;i++)
  14. {
  15. System.out.println(Thread.currentThread().getName()+" : "+i);
  16. if(i==20)
  17. {
  18. new FirstThreadTest().start();
  19. new FirstThreadTest().start();
  20. }
  21. }
  22. }
  23. }
скопировать код

Метод Thread.currentThread() в приведенном выше коде возвращает текущий исполняемый объект потока. Метод getName() возвращает имя потока, вызвавшего этот метод.

2. Создайте класс потока через интерфейс Runnable.

(1) Определите класс реализации исполняемого интерфейса и перепишите метод run() интерфейса.Тело метода run() также является телом выполнения потока потока.

(2) Создайте экземпляр класса реализации Runnable и используйте этот экземпляр в качестве цели Thread для создания объекта Thread, который является реальным объектом потока.

(3) Вызовите метод start() объекта потока, чтобы запустить поток.

  1. package com.thread;
  2. public class RunnableThreadTest implements Runnable
  3. {
  4. private int i;
  5. public void run()
  6. {
  7. for(i = 0;i <100;i++)
  8. {
  9. System.out.println(Thread.currentThread().getName()+" "+i);
  10. }
  11. }
  12. public static void main(String[] args)
  13. {
  14. for(int i = 0;i < 100;i++)
  15. {
  16. System.out.println(Thread.currentThread().getName()+" "+i);
  17. if(i==20)
  18. {
  19. RunnableThreadTest rtt = new RunnableThreadTest();
  20. new Thread(rtt,"新线程1").start();
  21. new Thread(rtt,"新线程2").start();
  22. }
  23. }
  24. }
  25. }
скопировать код

3. Создавайте темы через Callable и Future

(1) Создайте класс реализации интерфейса Callable и реализуйте метод call().Метод call() будет использоваться как тело выполнения потока и иметь возвращаемое значение.

(2) Создайте экземпляр класса реализации Callable и используйте класс FutureTask для переноса объекта Callable, который инкапсулирует возвращаемое значение метода call() объекта Callable.

(3) Используйте объект FutureTask в качестве цели объекта Thread для создания и запуска нового потока.

(4) Вызовите метод get() объекта FutureTask, чтобы получить возвращаемое значение после завершения выполнения дочернего потока.

  1. package com.thread;
  2. import java.util.concurrent.Callable;
  3. import java.util.concurrent.ExecutionException;
  4. import java.util.concurrent.FutureTask;
  5. public class CallableThreadTest implements Callable<Integer>
  6. {
  7. public static void main(String[] args)
  8. {
  9. CallableThreadTest ctt = new CallableThreadTest();
  10. FutureTask<Integer> ft = new FutureTask<>(ctt);
  11. for(int i = 0;i < 100;i++)
  12. {
  13. System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);
  14. if(i==20)
  15. {
  16. new Thread(ft,"有返回值的线程").start();
  17. }
  18. }
  19. try
  20. {
  21. System.out.println("子线程的返回值:"+ft.get());
  22. } catch (InterruptedException e)
  23. {
  24. e.printStackTrace();
  25. } catch (ExecutionException e)
  26. {
  27. e.printStackTrace();
  28. }
  29. }
  30. @Override
  31. public Integer call() throws Exception
  32. {
  33. int i = 0;
  34. for(;i<100;i++)
  35. {
  36. System.out.println(Thread.currentThread().getName()+" "+i);
  37. }
  38. return i;
  39. }
  40. }
скопировать код

Сравнение трех способов создания потоков

Когда многопоточность Transcend реализуется путем реализации интерфейсов Runnable и Callable, преимущества заключаются в следующем:

Класс потока просто реализует интерфейс Runnable или Callable, а также может наследоваться от других классов.

Таким образом, несколько потоков могут совместно использовать один и тот же целевой объект, поэтому очень удобно, чтобы несколько одних и тех же потоков обрабатывали один и тот же ресурс, чтобы ЦП, код и данные можно было разделить для формирования четкой модели, которая может лучше отражать объект. ориентированное мышление.

Недостатки:

Программирование немного сложнее, если вы хотите получить доступ к текущему потоку, вы должны использовать метод Thread.currentThread().

Преимущества создания нескольких потоков путем наследования от класса Thread:

Написание простое.Если вам нужно получить доступ к текущему потоку, вам не нужно использовать метод Thread.currentThread(), вы можете напрямую использовать его для получения текущего потока.

Недостатки:

Класс потока уже наследует класс Thread, поэтому он не может наследовать другие родительские классы.

В чем разница между sleep(), join(), yield()

1. Метод сна()

Засыпает (приостанавливает выполнение) выполняющийся в данный момент поток на указанное количество миллисекунд, в зависимости от точности системных таймеров и планировщиков. Дает другим потокам возможность продолжить выполнение, но не снимает блокировку объекта. То есть, если есть синхронизированный синхронизированный блок, другие потоки по-прежнему не могут получить доступ к общим данным. Обратите внимание, что этот метод должен перехватывать исключения.

Например, если есть два потока, выполняющихся одновременно (без Synchronized), один поток имеет приоритет MAX_PRIORITY, а другой — MIN_PRIORITY.Если нет метода Sleep(), только после выполнения потока с высоким приоритетом завершен, низкоприоритетный поток может выполняться, но когда высокоприоритетный поток приостанавливается (5000), низкоприоритетный поток имеет возможность выполниться.
Короче говоря, sleep() может дать шанс на выполнение низкоприоритетным потокам, и, конечно же, он также может дать шанс на выполнение высокоприоритетным потокам того же приоритета.

2. метод доходности ()

Метод yield() аналогичен методу sleep() и не снимает "флаг блокировки". Разница в том, что он не имеет параметров, то есть метод yield() просто возвращает текущий поток в исполняемый файл. состояние, поэтому поток, который выполняет yield(), может быть выполнен сразу после перехода в исполняемое состояние. Кроме того, метод yield() может дать шанс на выполнение только потоку с таким же или высоким приоритетом, что также отличается от метода yield(). Метод сна().

3. Метод присоединения()

Нестатический метод потока join() позволяет потоку B «присоединиться» к хвосту другого потока A. B не может работать, пока A не завершит выполнение.

Thread t = new MyThread(); t.start(); t.join();

Гарантирует, что текущий поток перестанет выполняться до тех пор, пока не завершится поток, к которому он присоединяется. Однако текущий поток не нужно останавливать, если поток, к которому он присоединяется, неактивен.

Разговор о принципе CountDownLatch

Ссылаться на:

Анализируем принцип реализации CountDownLatch

Когда использовать CountDownLatch

Параллельное программирование на Java: CountDownLatch, CyclicBarrier и Semaphore

Расскажите о принципе CyclicBarrier

Ссылаться на:

Обзор JUC — базовая реализация и принцип CyclicBarrier

Расскажите о принципе семафора.

Многопоточность JAVA — семафор (Семафор)

Обзор JUC - реализация и принцип семафора

Разговор о принципе Exchanger

Пример приложения и принципиальный анализ java.util.concurrent.Exchanger

Разговор о разнице между CountDownLatch и CyclicBarrier

Постарайтесь максимально упростить разницу между CyclicBarrier и CountDownLatch.

Анализ принципа ThreadLocal

Параллельное программирование на Java: подробный взгляд на ThreadLocal

Расскажите о принципе реализации пула потоков

В основном принцип реализации ThreadPoolExecutor

Параллельное программирование на Java: использование пулов потоков

Несколько способов пула потоков

newFixedThreadPool(int nThreads)
Создайте пул потоков фиксированной длины, создайте поток каждый раз при отправке задачи, пока не будет достигнуто максимальное количество пулов потоков, при этом размер потока не изменится, а когда поток завершится с неожиданной ошибкой, поток пул будет пополняться новым потоком

newCachedThreadPool()
Создайте кэшируемый пул потоков. Если размер пула потоков превышает потребность в обработке, простаивающие потоки будут автоматически перезапущены, а когда потребность возрастет, новые потоки могут быть добавлены автоматически. Размер пула потоков не ограничен.

newSingleThreadExecutor()
Это однопоточный Executor, создающий один рабочий поток для выполнения задач, если этот поток аварийно завершается, то создается новый на его место, его особенность в том, что задачи выполняются последовательно в том порядке, в котором они поставлены в очередь.

newScheduledThreadPool(int corePoolSize)
Создает пул потоков фиксированной длины и выполняет задачи с задержкой или по времени, аналогично Timer.

взять каштан

  1. private static final Executor exec=Executors.newFixedThreadPool(50);
  2. Runnable runnable=new Runnable(){
  3. public void run(){
  4. ...
  5. }
  6. }
  7. exec.execute(runnable);
  8. Callable<Object> callable=new Callable<Object>() {
  9. public Object call() throws Exception {
  10. return null;
  11. }
  12. };
  13. Future future=executorService.submit(callable);
  14. future.get(); // 等待计算完成后,获取结果
  15. future.isDone(); // 如果任务已完成,则返回 true
  16. future.isCancelled(); // 如果在任务正常完成前将其取消,则返回 true
  17. future.cancel(true); // 试图取消对此任务的执行,true中断运行的任务,false允许正在运行的任务运行完成
скопировать код

Ссылаться на:

Несколько способов создания пула потоков

жизненный цикл нити

новый(Новый),готов(работает),бегать(Бег),блокировать(заблокировано) иумри(Dead)5 штатов

(1) Пять состояний жизненного цикла

Новый (новая тема)
При создании экземпляра (объекта) класса Thread поток переходит во вновь созданное состояние (не запущен).
Например: Thread t1=new Thread();

готовый (запускаемый)
Поток был запущен и ожидает выделения кванта времени ЦП, то есть поток стоит в очереди готовности и в это время ожидает ресурсов ЦП. Например:t1.start();

Бег
Поток получает ресурс ЦП и выполняет задачу (метод run()).В это время, если поток автоматически не отдаст ресурс ЦП или не войдет поток с более высоким приоритетом, поток будет продолжать работать до конца.

мертвых
Когда поток выполняется или уничтожается другими потоками, поток переходит в мертвое состояние и больше не может переходить в состояние готовности для ожидания выполнения.

Естественное завершение: завершается после запуска метода run() в обычном режиме.

Аварийное завершение: звонокstop()способ остановить выполнение потока

заблокирован
По какой-то причине запущенный поток уступает ЦП и приостанавливает собственное выполнение, т.е. переходит в заблокированное состояние.

Спящий режим: используйте метод sleep(long t), чтобы перевести поток в спящий режим. Спящий поток может перейти в состояние готовности по истечении указанного времени.

Ожидание: вызовите метод ожидания(). (Вызовите метод notify(), чтобы вернуться в состояние готовности)

Заблокировано другим потоком: вызовите метод suspend(). (вызовите метод возобновления() для возобновления)

Ссылаться на:

жизненный цикл нити

замок механизм

Разговор о безопасности потоков

Безопасность потоков относится к управлению упорядоченным доступом или модификацией ресурса несколькими потоками без конфликтов между этими потоками.
В Java безопасность потоков обычно отражается в двух аспектах:
1. Доступ (чтение и изменение) нескольких потоков к одному и тому же экземпляру Java не будет мешать друг другу, что в основном отражено в ключевом слове synchronized. Например, ArrayList и Vector, HashMap и Hashtable (последний имеет ключевое слово synchronized перед каждым методом). Проблема возникает, если вы удаляете элемент из другого потока, в то время как интератор является объектом списка.
2. Каждый поток имеет свое собственное поле, которое не используется несколькими потоками. В основном это отражено в классе java.lang.ThreadLocal без поддержки ключевых слов Java, таких как static и transient.

изменчивый принцип реализации

Talk about concurrency (1) — глубокий анализ принципа реализации Volatile

Пессимистическая блокировка Оптимистическая блокировка

оптимистическая блокировка пессимистическая блокировка
это мысль. Можно использовать разными способами.

такие как базы данных.
Пессимистическая блокировка предназначена для обновления (блокировка строк запроса).
Оптимистическая блокировка — это поле версии (сравните с предыдущим номером версии, обновите, если он совпадает, и повторите операцию чтения-сравнения-записи, если она не удалась).

Сторона JDK:
Пессимистическая блокировка синхронизируется
Оптимистическая блокировка — это атомарный класс (реализованный внутри с помощью CAS).

По сути, это пессимистичный замок, который всегда кто-нибудь у меня отнимет.
Оптимистичный замок считает, что в принципе его никто не схватит.

Оптимистическая блокировка CAS

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

CAS — это атомарная операция обновления, она сравнивает, совпадает ли текущее значение с входящим значением, и если оно совпадает, оно обновляется, в противном случае происходит сбой.
CAS в лучшем случае является реализацией операции записи оптимистичной блокировки, также возможна блокировка без CAS.

АВА-проблема

ABA: если другой поток изменяет значение V и предполагает, что оно изначально было A, сначала изменяет его на B, а затем изменяет его обратно на A, операция CAS текущего потока не может определить, изменилось ли текущее значение V.

Ссылаться на:

Проблемы Java CAS и ABA

Бизнес-сценарии и методы реализации оптимистической блокировки

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

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

Основные статьи

хранилище данных

Примечания по использованию индексов MySQL

Ссылаться на:

Навыки использования индекса MySQL и меры предосторожности

Разговор о дизайне против шаблонов

Ссылаться на:

9 антипаттернов, о которых должен знать каждый программист

Разговор о дизайне подбиблиотеки и подтаблицы

Используйте сценарии и методы проектирования подтаблицы и подбиблиотеки

Распределенная дилемма и контрмеры, вызванные подбазой данных и подтаблицей

Руководство по серверу Хранение данных | MySQL (09) Распределенная дилемма и меры противодействия, вызванные секционированием базы данных и таблиц

Разговор об оптимизации SQL

Несколько методов оптимизации sql

Проблема взаимоблокировки, с которой столкнулся MySQL

Ссылаться на:

Классические и распространенные причины взаимоблокировки и решения, когда Mysql является параллельным

InnoDB и MyISAM для механизмов хранения

1) InnoDB поддерживает транзакции, MyISAM — нет, что очень важно. Транзакция — это расширенный метод обработки, например, при добавлении, удалении и изменении некоторых столбцов, пока возникает ошибка, ее можно откатить и восстановить, а MyISAM — нет.

2) MyISAM подходит для приложений, основанных на запросах и вставках, а InnoDB подходит для частых изменений и приложений, требующих высокой безопасности.

3) InnoDB поддерживает внешние ключи, MyISAM — нет.

4) Начиная с MySQL 5.5.5, InnoDB является движком по умолчанию.

5) InnoDB не поддерживает индексы типа FULLTEXT.

6) InnoDB не сохраняет количество строк в таблице, например select count() из таблицы, InnoDB необходимо просмотреть всю таблицу, чтобы вычислить количество строк, но MyISAM просто считывает количество сохраненных строк. Обратите внимание, что при подсчете () содержит, где условие MyISAM также должно сканировать всю таблицу

7) Для саморастущих полей InnoDB должен содержать индекс только этого поля, но можно установить совместный индекс с другими полями в таблице MyISAM.

8) При очистке всей таблицы InnoDB удаляет построчно, что очень медленно. MyISAM перестроит таблицу

9) InnoDB поддерживает блокировку строк (в некоторых случаях блокируется вся таблица, например, при обновлении таблицы устанавливается a=1, где пользователю нравится «%lee%»

Ссылаться на:

Сводка MyIsam и Innodb по движку хранения MySQL

Принцип индексации базы данных

Ссылаться на:

blog.CSDN.net/С ветром 3051…

Зачем использовать B-дерево

Ввиду хороших характеристик позиционирования B-дерева, его часто используют в случаях со строгими требованиями к времени поиска, например:
1. Индекс B-дерева — это метод доступа и поиска файлов (называемых записями или ключами) в базе данных.
2. Узлы на жестком диске также представляют собой структуру B-дерева. По сравнению с памятью жестким дискам требуется в два раза больше времени для доступа к элементу данных, потому что механические части жестких дисков не могут считывать и записывать данные намного быстрее, чем память на чисто электронных носителях. По сравнению с бинарным деревом с одним узлом и двумя ветвями, B-дерево использует узлы с несколькими ветвями (называемые поддеревьями), чтобы уменьшить количество узлов, используемых при получении записей, тем самым достигая цели экономии времени доступа.

Разница между кластеризованным индексом и некластеризованным индексом

Ссылаться на:

Быстро понять кластеризованные и некластеризованные индексы

лимит 20000 загрузка очень медленная как решить

LIMIT n эквивалентен LIMIT 0,n

Подводя итог этому вопросу, пусть предел идет к индексу для запроса, например: порядок по索引字段, или корень, где условие перед пределом переходит в поле индекса и так далее.

Ссылаться на:

Ограничение подкачки MYSQL - слишком медленный метод оптимизации

Выбор подходящей схемы распределенного первичного ключа

Ссылаться на:

Краткое изложение схем генерации уникальных идентификаторов для распределенных систем

Выберите правильное решение для хранения данных

  • реляционная база данных MySQL

MySQL является одной из самых популярных реляционных баз данных и широко используется в интернет-продуктах. В общем, база данных MySQL является первым выбором, и в основном от 80% до 90% сценариев основаны на базе данных MySQL. Поскольку для управления требуется реляционная база данных, а в бизнесе много транзакционных операций, необходимо обеспечить строгую согласованность транзакций. В то же время могут быть и сложные SQL-запросы. Стоит отметить, что на ранней стадии совместный запрос таблицы должен быть сведен к минимуму, чтобы облегчить подбазу данных и подтаблицу базы данных при увеличении объема данных на более позднем этапе.

  • База данных в памяти Redis

С ростом объема данных MySQL больше не может удовлетворять потребности крупномасштабных интернет-приложений. Поэтому Redis хранит данные на основе памяти, что может значительно повысить производительность запросов и дополнить архитектуру продукта. Например, чтобы улучшить скорость доступа к серверному интерфейсу, данные хотспотов с высокой частотой считывания должны храниться в Redis как можно больше. Это очень типичная стратегия обмена пространства на время, использования большего объема памяти в обмен на ресурсы ЦП и увеличения скорости работы программы за счет увеличения потребления памяти системой.

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

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

  • База данных документов MongoDB

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

Кроме того, объем данных в системе журналов очень велик.Если вы используете базу данных MongoDB для хранения этих данных, используете сегментированный кластер для поддержки массивных данных и одновременно используете возможность агрегированного анализа и MapReduce, это хороший выбор.

MongoDB также подходит для хранения данных большого размера.Решение для хранения данных GridFS представляет собой распределенную систему хранения файлов на основе MongoDB.

  • База данных семейств столбцов HBase

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

  • Полнотекстовый поисковик ElasticSearch

В общем, нечеткий запрос реляционной базы данных выполняется аналогичным образом. Среди них, например, «значение%» может использовать индекс, но для такого метода, как «%значение%», для выполнения полного запроса таблицы нет проблем с производительностью в таблице с небольшим объемом данных, но для массивных данных, полное сканирование таблицы - очень страшная вещь. Являясь распределенной системой поиска и анализа в реальном времени, основанной на системе полнотекстового поиска Apache Lucene, ElasticSearch подходит для обработки сценариев приложений поиска в реальном времени. Кроме того, используя механизм полнотекстового поиска ElasticSearch, он также может поддерживать расширенные функции, такие как запрос с несколькими входами, сопоставление степени и веса, автоматическая ассоциация и исправление орфографических ошибок. Таким образом, ElasticSearch можно использовать в качестве дополнения к функции полнотекстового поиска реляционных баз данных, а копия данных для полнотекстового поиска может быть кэширована в ElasticSearch для достижения цели обработки сложных деловых и повышение скорости запросов.

ElasticSearch подходит не только для сценариев поиска, но и для сценариев обработки и анализа журналов. Известное решение для обработки журналов ELK состоит из трех компонентов: ElasticSearch, Logstash и Kibana, включая сбор журналов, агрегацию, многомерный запрос и визуальное отображение.

Правила ObjectId

Ссылаться на:

Заметки об исследовании MongoDB ~ Дизайн первичного ключа ObjectId

Правила генерации для ObjectId _id в mongodb

Расскажите о сценариях использования MongoDB

Ссылаться на:

В каких сценариях следует использовать MongoDB?

Перевернутый индекс

Ссылаться на:

Что такое инвертированный индекс?

Расскажите о сценариях использования ElasticSearch

В общем, нечеткий запрос реляционной базы данных выполняется аналогичным образом. Среди них, например, «значение%» может использовать индекс, но для такого метода, как «%значение%», для выполнения полного запроса таблицы нет проблем с производительностью в таблице с небольшим объемом данных, но для массивных данных, полное сканирование таблицы - очень страшная вещь. Являясь распределенной системой поиска и анализа в реальном времени, основанной на системе полнотекстового поиска Apache Lucene, ElasticSearch подходит для обработки сценариев приложений поиска в реальном времени. Кроме того, используя механизм полнотекстового поиска ElasticSearch, он также может поддерживать расширенные функции, такие как запрос с несколькими входами, сопоставление степени и веса, автоматическая ассоциация и исправление орфографических ошибок. Таким образом, ElasticSearch можно использовать в качестве дополнения к функции полнотекстового поиска в реляционных базах данных, а копия данных для полнотекстового поиска может быть кэширована в ElasticSearch для достижения цели обработки сложных деловых и повышение скорости запросов.

использование кеша

Какие бывают типы Redis

Redis поддерживает пять типов данных: string (строка), hash (хэш), list (список), set (коллекция) и zset (отсортированный набор: упорядоченный набор).

Ссылаться на:
Типы данных Redis

Внутренняя структура Redis

Ссылаться на:

Внутренняя структура данных Redis объясняется простым языком

Расскажите о сценариях использования Redis

С ростом объема данных MySQL больше не может удовлетворять потребности крупномасштабных интернет-приложений. Поэтому Redis хранит данные на основе памяти, что может значительно повысить производительность запросов и дополнить архитектуру продукта. Например, чтобы улучшить скорость доступа к серверному интерфейсу, данные хотспотов с высокой частотой считывания должны храниться в Redis как можно больше. Это очень типичная стратегия обмена пространства на время, использования большего объема памяти в обмен на ресурсы ЦП и увеличения скорости работы программы за счет увеличения потребления памяти системой.

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

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

Механизм сохранения Redis

Ссылаться на:

Сохранение и механизм кэширования Redis

Как Redis реализует постоянство

Ссылаться на:

Как Redis реализует постоянство

Схема и реализация кластера Redis

Ссылаться на:

Анализ основных архитектурных решений кластера Redis

Почему Redis однопоточный?

Для чистого сетевого ввода-вывода, после того как количество достигает определенного уровня, многопоточность действительно имеет преимущества — но это не чистая многопоточность, а у каждого потока своя модель типа epoll, то есть смесь многопоточности и мультиплексирование .

Обычно мы начинаем с «но».
но.

Также рассмотрите объекты, с которыми работает Redis. Объекты, с которыми он работает, представляют собой структуры данных в памяти. Если вы работаете в нескольких потоках, вам необходимо заблокировать эти объекты. В конечном итоге производительность многопоточности улучшается, но эффективность каждого потока значительно падает. Да и логика программы серьезно усложняется.
Вы должны знать, что структура данных Redis — это не только простые ключи-значения, но и сложные структуры, такие как списки, хэши, карты и т. д. Эти структуры могут выполнять очень мелкие операции, такие как добавление элемента после длинного списка. ., добавление или удаление объекта из хэша и т.д. Эти операции могут также синтезировать группы MULTI/EXEC. Для такой операции может потребоваться много блокировок, что приведет к значительному увеличению затрат на синхронизацию. Это также влечет за собой негативное последствие, заключающееся в том, что хотя пропускная способность увеличивается, задержка ответа может увеличиваться.
Выбор Redis после взвешивания — использовать один поток, чтобы подчеркнуть гибкость собственных функций. На однопоточной основе любая атомарная операция может быть реализована практически бесплатно, независимо от того, насколько сложна структура данных, которую можно легко использовать, и даже можно использовать такие функции, как скрипты Lua. Это намного дороже для многопоточности.

Не все базы данных KV или in-memory должны быть однопоточными, например, ZooKeeper является многопоточным, в конце концов, это зависит от собственных пожеланий и компромиссов автора. Мощность одного потока на самом деле очень велика, а эффективность каждого ядра также очень высока.В современной виртуализированной среде облачная среда может быть полностью использована для повышения эффективности использования ресурсов. Многопоточность, естественно, может иметь более высокий предел производительности, чем однопоточность, но в современной вычислительной среде даже верхнего предела многопоточности на одной машине часто недостаточно.Что требует дальнейшего изучения, так это схема кластеризации с несколькими серверами. Этих многопоточных технологий в решении пока нет, поэтому модным решением является однопоточный многопроцессный кластер.

Автор: Духовный меч
Ссылка на сайт:Ууху. Call.com/question/23…
Источник: Чжиху
Авторские права принадлежат автору. Для коммерческих перепечаток, пожалуйста, свяжитесь с автором для получения разрешения, а для некоммерческих перепечаток, пожалуйста, укажите источник.

сбой кеша

Ссылаться на:

Стойкость Redis

Деградация кэша

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

Разумность использования кеша

Ссылаться на:

Redis Combat (1) Рациональность использования кеша

очередь сообщений

Сценарии использования очередей сообщений

В основном он решает такие проблемы, как связывание приложений, асинхронные сообщения и отключение трафика.

Введение в четыре сценария использования очереди сообщений

Решение для компенсации повторной передачи сообщений

Ссылаться на:

Механизм обмена сообщениями JMS

Идемпотентное решение сообщений

Ссылаться на:

Как добиться идемпотентности сообщений в MQ

решение для стека сообщений

Ссылаться на:

Руководство администратора Sun Java System Message Queue 3.7 UR1

Как реализовать очередь сообщений самостоятельно

Ссылаться на:

Самостоятельная реализация JMS очереди сообщений

Как обеспечить порядок сообщений

Ссылаться на:

Как эксклюзивная потребительская функция очереди сообщений обеспечивает упорядоченность сообщений и предотвращает разделение мозгов?

Рамочные статьи

Spring

В чем разница между BeanFactory и ApplicationContext

Как следует из названия, основной концепцией beanfactory является фабрика компонентов, которая используется для управления жизненным циклом компонентов, а концепция контекста приложения богаче. более широкий диапазон.Он наследует от Bean factory не только наследует от этого интерфейса, но и наследует другие интерфейсы, поэтому он имеет не только концепцию bean factory, но и контекст прикладной системы. Его первоначальный дизайн должен быть все- включая внешнее воздействие Комплексный API.

Жизненный цикл Spring Bean

Ссылаться на:

Подробное объяснение жизненного цикла Spring Bean

Как реализован Spring IOC

Ссылаться на:

Spring: интерпретация исходного кода принципа Spring IOC

Разговор о весеннем АОП

Ссылаться на:

Подробное объяснение Spring AOP

Принцип реализации Spring АОП

Ссылаться на:

Принцип реализации Spring АОП

Динамические прокси (cglib и JDK)

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

Динамический прокси-сервер cglib использует пакет с открытым исходным кодом asm, загружает файл класса класса прокси-объекта и генерирует подклассы, изменяя его байт-код.

1. Если целевой объект реализует интерфейс, динамический прокси JDK будет использоваться для реализации АОП по умолчанию.
2. Если целевой объект реализует интерфейс, вы можете принудительно использовать CGLIB для реализации АОП.
3. Если целевой объект не реализует интерфейс, необходимо использовать библиотеку CGLIB, и Spring автоматически преобразует динамический прокси JDK в CGLIB.

Как принудительно реализовать АОП с помощью CGLIB?
(1) Добавьте библиотеку CGLIB, SPRING_HOME/cglib/*.jar
(2) Добавить в файл конфигурации spring

Разница между динамическим прокси JDK и генерацией байт-кода CGLIB?
(1) Динамический прокси JDK может генерировать прокси только для классов, реализующих интерфейсы, но не для классов.
(2) CGLIB — это прокси для класса, в основном для создания подкласса для указанного класса и переопределения методов в нем.
Поскольку это наследование, лучше не объявлять класс или метод как final

Ссылаться на:

Говоря о разнице между двумя прокси-серверами Spring JDK и CGLIB

Реализация весенней транзакции

Ссылаться на:

Подробное объяснение программной транзакции и декларативной транзакции реализации управления транзакциями Spring

Основной принцип транзакции Spring

Ссылаться на:

Глубокое понимание принципов транзакций Spring

Как настроить функцию реализации аннотации

Его можно комбинировать с АОП Spring для перехвата и извлечения аннотаций.

Общий процесс таков:
1. Создайте новую аннотацию @MyLog и добавьте ее в метод, который необходимо аннотировать.
2. Создайте новый класс MyLogAspect и сделайте этот класс классом аспекта с помощью аннотации @Aspect.
3. Укажите pointcut через @Pointcut, указанный здесь pointcut — это тип аннотации MyLog, то есть метод, модифицированный аннотацией @MyLog, введите pointcut.
4. Методы в MyLogAspect определяют бизнес-операции, которые необходимо выполнить, добавляя аннотации уведомлений (@Before, @Around, @AfterReturning, @AfterThrowing, @After и другие уведомления).

Рабочий процесс Spring MVC

один,Сначала опишите текстом

1. Пользователь отправляет запрос DispatchServlet

2. DispatchServlet запрашивает конкретный обработчик в соответствии с путем запроса.

3. HandlerMapping возвращает HandlerExecutionChain в DispatchServlet.

HandlerExecutionChain: коллекция обработчиков и перехватчиков

4. DispatchServlet вызывает адаптер HandlerAdapter

5. HandlerAdapter вызывает определенный обработчик для обработки бизнеса.

6. Обработчик возвращает конкретный ModelAndView адаптеру в конце обработки.

ModelAndView: модель -> модель данных, представление -> имя представления.

7. Адаптер отправляет ModelAndView в DispatchServlet.

8. DispatchServlet дает имя представления преобразователю представлений ViewResolver.

9.ViewResolver возвращает определенное представление DispatchServlet

10. Рендеринг вида

11. Показать пользователям

2. Анализ чертежа

Конфигурация SpringMvc

Процесс запуска Spring MVC

Ссылаться на:

Подробное объяснение процесса запуска SpringMVC (li)

Принцип реализации синглтона Spring

Ссылаться на:

Низкоуровневая реализация одноэлементного шаблона Spring

Какие шаблоны проектирования используются в среде Spring

В фреймворке Spring используется большое количество шаблонов проектирования, наиболее типичные из которых перечислены ниже:

Режим прокси — больше используется в АОП и удаленном взаимодействии.
Одноэлементный режим — bean-компоненты, определенные в файлах конфигурации Spring, по умолчанию используют одноэлементный режим.
Шаблонный метод — используется для решения проблемы дублирования кода. Например, RestTemplate,JmsTemplateJpaTemplate。
Factory Pattern — BeanFactory используется для создания экземпляров объектов.
адаптер – весна аоп
декоратор — хеш-мапер данных spring
Observer — Spring, управляемая временем модель
callback — интерфейс обратного вызова Spring ResourceLoaderAware
Передний контроллер — Spring использует передний контроллер DispatcherServlet для отправки запросов.

Другие продукты Spring (Srping Boot, Spring Cloud, Spring Security, Spring Data, Spring AMQP и т. д.)

Ссылаться на:

Расскажите о семье Весенних.

Netty

Почему выбирают Нетти

Netty — одна из самых популярных инфраструктур NIO в отрасли. Ее надежность, функциональность, производительность, настраиваемость и расширяемость не имеют себе равных в своем классе. Она была проверена сотнями коммерческих проектов, таких как Hadoop. Фреймворк RPC Avro использует Netty. как коммуникативная основа. Многие другие распространенные в отрасли платформы RPC и распределенных сервисов также используют Netty для создания высокопроизводительных возможностей асинхронной связи.

Преимущества Netty резюмируются следующим образом:

  • API прост в использовании, а порог освоения низкий;
  • Мощный, предустановленный набор функций кодека, поддержка различных основных протоколов;
  • Широкие возможности настройки, коммуникационная структура может быть гибко расширена с помощью ChannelHandler;
  • Высокая производительность по сравнению с другими основными инфраструктурами NIO в отрасли, Netty имеет лучшую общую производительность;
  • Сообщество активное, цикл итерации версии короткий, найденные ошибки можно вовремя исправить, а новые функции будут добавляться;
  • После крупномасштабного коммерческого тестирования качество было подтверждено. Он был успешно коммерциализирован во многих отраслях, таких как Интернет, большие данные, онлайн-игры, корпоративные приложения и телекоммуникационное программное обеспечение, что доказывает, что оно полностью соответствует коммерческим стандартам различных отраслей.

Именно из-за этих преимуществ Netty постепенно стала предпочтительной средой для программирования Java NIO.

Расскажите о сценариях использования Netty в бизнесе

11 вопросов и ответов на тему «Почему Netty»

Нативный NIO имеет ошибку epoll в JDK 1.7.

Это приводит к тому, что опрос Selector пуст, и в конечном итоге ЦП достигает 100%. Официальный сайт утверждает, что проблема была исправлена ​​в обновлении 18 версии JDK1.6, но проблема все еще существует до версии JDK1.7, но вероятность появления BUG немного снижена, и принципиально она не решена. . Ошибка и сообщение об ошибке, связанное с этой ошибкой, можно найти по ссылке ниже.

Не говорите .java.com/, но база данных...

Не говорите .java.com/, но база данных...

Стек исключений выглядит следующим образом:

  1. java.lang.Thread.State: RUNNABLE
  2. at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
  3. at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)
  4. at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)
  5. at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)
  6. - locked <0x0000000750928190> (a sun.nio.ch.Util$2)
  7. - locked <0x00000007509281a8> (a java.util.Collections$ UnmodifiableSet)
  8. - locked <0x0000000750946098> (a sun.nio.ch.EPollSelectorImpl)
  9. at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
  10. at net.spy.memcached.MemcachedConnection.handleIO(Memcached Connection.java:217)
  11. at net.spy.memcached.MemcachedConnection.run(MemcachedConnection. java:836)

Что такое склеивание/распаковка TCP

Ссылаться на:

Залипание TCP, распаковка и решения

Решение проблемы склеивания/распаковки TCP

Ссылаться на:

Залипание TCP, распаковка и решения

Модель потоков Netty

Ссылаться на:

Netty4 Actual Глава 15: Выбор правильной модели многопоточности

Разговор о нулевой копии Нетти

Ссылаться на:

Понимание механизма Zero-Copy в Netty

Внутренний процесс выполнения Netty

Ссылаться на:

Netty: поток обработки данных

Реализация переподключения Netty

Ссылаться на:

Реализация переподключения Netty Client

Микросервисы

Микросервисы

Как разделить переднюю и заднюю части

Ссылаться на:

Опыт реализации разделения фронта и бэкенда

Какие фреймворки являются микросервисами

Spring Cloud, Dubbo, HSF и т. д.

Как вы понимаете структуру RPC

Цель RPC — позволить вам вызывать удаленный метод локально, и этот вызов прозрачен для вас, вы не знаете, где развернут вызываемый метод. Разделение служб через RPC является реальной целью использования RPC.

Расскажите о принципе реализации RPC

Ссылаться на:

Принципы RPC, которые вы должны знать

Внедрение RPC Framework с нуля — принцип и реализация RPC

Расскажите о принципе реализации Dubbo

Dubbo предоставляет функции, предоставляет базовые функции — вызовы RPC, предоставляет дополнительные функции, управление сервисами SOA.
При запуске dubbo ищет доступных удаленных сервис-провайдеров, при вызове интерфейса вызывает не локальную реализацию окончательно, а через процесс перехвата вызова (и с использованием динамической прокси-функции JDK) через серию сериализаций, удаленных обмен данными и анализ протоколов.Последний звонок удаленному поставщику услуг.

Ссылаться на:

Анализ Даббо и принципиальный анализ

Как вы понимаете RESTful

REST — это архитектурный стиль программного обеспечения и стиль дизайна, который является архитектурным стилем ресурсо-ориентированных сетевых гипермедиа-приложений. Он в основном используется для создания легковесных, удобных в сопровождении и масштабируемых веб-сервисов. Службы на основе REST называются службами RESTful. REST не зависит от какого-либо протокола, но почти каждая служба RESTful использует HTTP в качестве базового протокола, а RESTful использует метод http для идентификации операций, например:

http://127.0.0.1/user/1GET Запрос пользовательских данных на основе идентификатора пользователя
http://127.0.0.1/userPOST добавить пользователя
http://127.0.0.1/userPUT изменить информацию о пользователе

http://127.0.0.1/userУДАЛИТЬ удалить информацию о пользователе

Расскажите о том, как разработать хороший API

Ссылаться на:

Как разработать хороший API?

Как понять идемпотентность RESTful API

Ссылаться на:

Как понять идемпотентность RESTful

Как обеспечить идемпотентность интерфейсов

Ссылаться на:

Идемпотентность внутренних интерфейсов

Разговор о теореме CAP и теории BASE

Ссылаться на:

Принцип CAP и идея BASE

Как учитывать согласованность данных

Ссылаться на:

Решение для согласованности транзакций распределенной системы

Разговор о реализации возможной согласованности

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

Ссылаться на:

Окончательная схема согласованности в распределенной системе

Что вы думаете о микросервисах

  • Небольшой: микросервисы имеют небольшой размер.
  • Независимый: может быть развернут и работать независимо.
  • Легкий: используйте легкие механизмы и архитектуры связи.
  • Свободная связь: существует слабая связь между службами.

Разница между микросервисами и SOA

Думайте о микросервисах как о SOA без ESB. ESB — это центральная шина в архитектуре SOA, граф проектирования должен быть звездообразным, а микросервис — децентрализованной распределенной программной архитектурой.

Ссылаться на:

Разница между SOA и микросервисами

Как разделить услуги

Ссылаться на:

Микросервисная архитектура (2): как разбить приложение на несколько сервисов

Как микросервисы управляют базами данных

Ссылаться на:

Как управлять данными в микросервисах

Как бороться с исключениями из цепочек вызовов микросервисов

Ссылаться на:

Устраните камень преткновения: решение сложного вызова службы микросервисов

Для быстрого отслеживания и обнаружения проблем

Ссылаться на:

Как реализовать распределенную трассировку в микросервисной архитектуре?

Безопасность для микросервисов

Ссылаться на:

О безопасности микросервисов

распределенный

Расскажите об использовании распределенных сценариев в бизнесе

Во-первых, решение для совместного использования сеанса java-кластера:
1. Шифрование файлов cookie на стороне клиента. (Обычно используется в системах корпоративного уровня в интрасети, требуется, чтобы файл cookie в браузере пользователя нельзя было отключить. Если отключить, решение не удастся).
2. В кластере каждый сервер приложений обеспечивает функцию репликации сеанса, и эту функцию реализуют и tomcat, и jboss. Особенности: Производительность резко падает с увеличением сервера, из-за чего легко вызвать широковещательные штормы; данные сеанса необходимо сериализовать, что влияет на производительность.
3. Сохранение сеанса, используйте базу данных для сохранения сеанса. Даже если сервер выйдет из строя, сессия в базе данных все равно существует. Особенности: каждый раз, когда запрашивается сеанс, база данных должна быть прочитана и записана, что приведет к снижению производительности. Использование базы данных в оперативной памяти повысит производительность, но данные будут потеряны во время простоя (например, время простоя Alipay с аварийным восстановлением в том же городе и аварийным восстановлением за пределами площадки).
4. Используйте общее хранилище для сохранения сессий. Как и в случае с базой данных, даже если она выйдет из строя, все будет в порядке. По сути, это выделенный сервер, все это реализовано для сессий. Особенности: Частая сериализация и десериализация повлияют на производительность.
5. Используйте memcached для сохранения сеанса. По сути, это решение для базы данных в оперативной памяти. Особенности: Данные, хранящиеся в memcached, необходимо сериализовать, что крайне неэффективно.

2. Решения для распределенных транзакций:
1. Решение TCC: попробуйте подтвердить отмену.

Ссылаться на:
Почему традиционная распределенная транзакция больше не подходит для микросервисной архитектуры?

Распределенное решение сеанса

1. Шифрование файлов cookie на стороне клиента. (Обычно используется в системах корпоративного уровня в интрасети, требуется, чтобы файл cookie в браузере пользователя нельзя было отключить. Если отключить, решение не удастся).
2. В кластере каждый сервер приложений обеспечивает функцию репликации сеанса, и эту функцию реализуют и tomcat, и jboss. Особенности: Производительность резко падает с увеличением сервера, из-за чего легко вызвать широковещательные штормы; данные сеанса необходимо сериализовать, что влияет на производительность.
3. Сохранение сеанса, используйте базу данных для сохранения сеанса. Даже если сервер выйдет из строя, сессия в базе данных все равно существует. Особенности: каждый раз, когда запрашивается сеанс, база данных должна быть прочитана и записана, что приведет к снижению производительности. Использование базы данных в оперативной памяти повысит производительность, но данные будут потеряны во время простоя (например, время простоя Alipay с аварийным восстановлением в том же городе и аварийным восстановлением за пределами площадки).
4. Используйте общее хранилище для сохранения сессий. Как и в случае с базой данных, даже если она выйдет из строя, все будет в порядке. По сути, это выделенный сервер, все это реализовано для сессий. Особенности: Частая сериализация и десериализация повлияют на производительность.
5. Используйте memcached для сохранения сеанса. По сути, это решение для базы данных в оперативной памяти. Особенности: Данные, хранящиеся в memcached, необходимо сериализовать, что крайне неэффективно.

Сценарий распределенной блокировки

Например, модификацией суммы в системе транзакций может одновременно управлять только один человек.Например, в сценарии seckill только один пользователь может получить ее одновременно, например, билет на вокзал и т. д.

Схема реализации распределенной блокировки

  1. Распределенная блокировка на основе базы данных
  2. Распределенная блокировка на основе кеша
  3. Распределенная блокировка на основе Zookeeper

Ссылаться на:

Несколько реализаций распределенных блокировок

Распределенная транзакция

Ссылаться на:

Глубокое понимание распределенных транзакций, решения для распределенных транзакций в условиях высокой параллелизма

Алгоритмы и реализации кластеризации и балансировки нагрузки

Ссылаться на:

Алгоритмы и средства балансировки нагрузки

Разговор о дизайне подбиблиотеки и подтаблицы

Ссылаться на:

Используйте сценарии и методы проектирования подтаблицы и подбиблиотеки

Распределенная дилемма и контрмеры, вызванные подбазой данных и подтаблицей

Ссылаться на:

Руководство по серверу Хранение данных | MySQL (09) Распределенная дилемма и меры противодействия, вызванные секционированием базы данных и таблиц

Безопасность и производительность

Контрольный вопрос

Элементы безопасности и угроза STRIDE

Защита от распространенных веб-атак

Атака и защита безопасности связи с сервером

Анализ принципа HTTPS

Атака с понижением HTTPS

Авторизация и аутентификация

управление доступом на основе ролей

Управление доступом на основе данных

оптимизация производительности

Каковы показатели эффективности

Как обнаружить узкие места в производительности

Общие средства настройки производительности

Расскажите о том, как вы выполняете настройку производительности в своем проекте.

Инжиниринг

анализ спроса

Как вы понимаете и разделяете прототипы требований

Расскажите о своем понимании функциональных требований

Расскажите о своем понимании нефункциональных требований

Какие взаимодействия и улучшения вы предлагаете для продукта?

Как вы понимаете болевые точки пользователей

Способность к проектированию

Расскажите нам о диаграммах UML, которые вы использовали в своем проекте.

Как вы относитесь к компонентизации

Как вы относитесь к сервитизации?

Как вы делаете доменное моделирование

Как вы рисуете границы домена

Расскажите о моделировании предметной области в вашем проекте

Разговор об эскизном дизайне

Шаблоны проектирования

Какие шаблоны проектирования используются в вашем проекте

Расскажите об анализе использования паттернов проектирования в распространенных фреймворках с открытым исходным кодом.

Расскажите о своем понимании принципов дизайна

23 дизайнерских шаблона Идеи дизайна

Сходства и различия между шаблонами проектирования, такие как разница между шаблоном стратегии и шаблоном состояния.

Комбинация между шаблонами проектирования, такими как практика шаблона стратегии + простой шаблон factory

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

бизнес инжиниринг

Как работает разделение интерфейса в вашей системе?

Расскажите о своем процессе разработки

Как вы общаетесь со своей командой

Как вы проводите код-ревью

Расскажите нам о своем понимании технологий и бизнеса

Расскажите об исключении, с которым вы часто сталкиваетесь в своем проекте.

Расскажите о самом сложном баге, с которым вы столкнулись в проекте, и как его решить

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

Как вы думаете, какие недостатки есть у вашего проекта?

Вы когда-нибудь сталкивались с CPU 100%, как устранить неполадки и решить

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

Расскажите о своей практике гибкой разработки

Расскажите о своей практике DevOps

Расскажите об одном из самых ценных проектов в вашей работе и о своей роли в этом процессе.

мягкая сила

Расскажите мне о своих основных моментах

Скажи мне, какую книгу ты недавно читал

Расскажите мне о технических книгах, которые вы считаете наиболее значимыми

что делать после работы

Обсудить направление личного развития

Расскажите нам, какими навыками, по вашему мнению, должен обладать разработчик сервера

Расскажите нам, что вы думаете об архитекторе и чем в основном занимается архитектор

Расскажите о техническом эксперте, которого вы понимаете

У меня есть общедоступная учетная запись WeChat, и я часто делюсь галантерейными товарами, связанными с технологией Java; если вам нравится мой обмен, вы можете использовать WeChat для поиска «Java Head» или «javatuanzhang», чтобы подписаться.