Обобщайте общие стратегии оптимизации для ежедневной разработки Java и постоянно обновляйте их.
По возможности используйте локальные переменные
Параметры, передаваемые при вызове метода, и временные переменные, созданные при вызове, сохраняются в стеке, что быстрее, а другие переменные, такие как статические переменные, переменные экземпляра и т. д., создаются в куче, что медленнее. Кроме того, переменные, созданные в стеке, исчезают по завершении метода, и дополнительная сборка мусора не требуется.
Закрыть поток вовремя
В процессе программирования на Java необходимо соблюдать осторожность при подключении к базе данных и операциях с потоками ввода-вывода, после использования вовремя закрывать ее для освобождения ресурсов. Поскольку работа с этими большими объектами вызовет много накладных расходов в системе, небольшая небрежность приведет к серьезным последствиям. А лучшее место для высвобождения ресурсов — этоfinally
кодовый блок.
Минимизируйте двойной подсчет переменных
Уточните концепцию, вызов метода, даже если в методе есть только один оператор, потребляет, включая создание кадра стека, защиту сцены при вызове метода и восстановление сцены при вызове метода. Так, например, следующая операция:
for (int i = 0; i < list.size(); i++){
...
}
Рекомендуется заменить на:
for (int i = 0, length = list.size(); i < length; i++){
...
}
Таким образом, когда list.size() большой, он значительно снижает потребление.
Попробуйте использовать стратегию ленивой загрузки, то есть создавайте ее по мере необходимости.
Например:
String str = "aaa";
if (i == 1){
  list.add(str);
}
Рекомендуется заменить на:
if (i == 1){
  String str = "aaa";
  list.add(str);
}
Используйте исключения с осторожностью
Исключения плохо влияют на производительность. Генерация исключения сначала создает новый объект, конструктор интерфейса Throwable называется namedfillInStackTrace()
Метод локальной синхронизации ,fillInStackTrace()
Метод проверяет стек и собирает информацию о трассировке вызовов. Всякий раз, когда создается исключение, виртуальная машина Java должна корректировать стек вызовов, поскольку во время обработки создается новый объект. Исключения должны использоваться только для обработки ошибок и не должны использоваться для управления ходом программы.
Если длину добавляемого контента можно оценить, укажите начальную длину базовых коллекций и классов инструментов, реализованных в виде массивов.
Например, ArrayList, LinkedLlist, StringBuilder, StringBuffer, HashMap, HashSet и т. д. В качестве примера возьмем StringBuilder:
- StringBuilder () // выделяют 16 символов пространства по умолчанию
- StringBuilder (целый размер) // по умолчанию назначается пространство для символов SIZE
- StringBuilder(String str) // 16 символов + символьное пространство str.length() выделяется по умолчанию
Вы можете установить его инициализирующую способность через конструктор класса (не только StringBuilder выше), что может значительно повысить производительность. Например, для StringBuilder длина указывает количество символов, которые может содержать текущий StringBuilder. Поскольку, когда StringBuilder достигает своей максимальной емкости, он увеличивает свою собственную емкость в 2 раза по сравнению с текущей емкостью плюс 2, всякий раз, когда StringBuilder достигает своей максимальной емкости, он должен создавать новый массив символов, а затем заменять старый символ. Содержимое массива копируется в новый массив символов — это очень затратная операция. Только представьте, если можно подсчитать, что в массиве символов будет храниться около 5000 символов без указания длины, ближайшая степень двойки к 5000 равна 4096, а двойка, добавляемая за каждое расширение, не имеет значения, то:
- На основе 4096 подайте заявку на массив символов размером 8194, что эквивалентно подаче заявки на массив символов размером 12290. Если вы можете указать вначале массив символов размером 5000, это сэкономит более удвоить пространство
- Скопируйте исходные 4096 символов в новый массив символов.
Таким образом, пространство памяти тратится впустую, а эффективность выполнения кода снижается. Поэтому нет ничего плохого в том, чтобы установить разумную емкость инициализации для базовых коллекций и классов инструментов, реализованных с помощью массивов, что даст немедленные результаты. Однако обратите внимание, чтоДля таких коллекций, как HashMap, которые реализованы в виде массивов + связанных списков, не устанавливайте начальный размер равным предполагаемому размеру, потому что возможность подключения только одного объекта к таблице почти равна нулю.. Начальный размер рекомендуется устанавливать равным степени 2. Если можно оценить, что имеется 2000 элементов, его можно установить как новый HashMap(128) или новый HashMap(256).
При копировании больших объемов данных используйте команду System.arraycopy().
Умножение и деление с использованием операций сдвига
Например:
for (val = 0; val < 100000; val += 5){
  a = val * 8;
  b = val / 2;
}
Использование операции сдвига позволяет значительно повысить производительность, т. к. в нижней части компьютера операция бита наиболее удобна и быстра, поэтому рекомендуется модифицировать ее как:
for (val = 0; val < 100000; val += 5){
  a = val << 3;
  b = val >> 1;
}
Хотя операция сдвига выполняется быстро, она может сделать код менее понятным, поэтому лучше добавить соответствующие комментарии.
Не продолжайте создавать ссылки на объекты внутри цикла
Например:
for (int i = 1; i <= count; i++){
Object obj = new Object();
}
Такой подход приведет к тому, что в памяти будет существовать количество ссылок на объекты объекта count.
Object obj = null;
for (int i = 0; i <= count; i++){
obj = new Object();
}
В этом случае в памяти находится только одна ссылка на объект Object.Каждый раз, когда используется new Object(), ссылка на объект Object указывает на другой объект, но в памяти находится только один объект, что значительно экономит место в памяти.
Исходя из соображений эффективности и проверки типов, массив следует использовать как можно чаще, а ArrayList следует использовать, когда невозможно определить размер массива.
Попробуйте использовать HashMap, ArrayList, StringBuilder. Если не требуется безопасность потоков, не рекомендуется использовать Hashtable, Vector и StringBuffer. Последние три вызывают снижение производительности из-за использования механизма синхронизации.
Старайтесь избегать произвольного использования статических переменных
Вы должны знать, что когда на объект ссылается переменная, определенная как статическая, то gc обычно не восстанавливает память кучи, занимаемую объектом, например:
public class A{
private static B b = new B();
}
В настоящее время жизненный цикл статической переменной b такой же, как у класса A. Если класс A не выгружен, объект B, на который указывает ссылка B, будет находиться в памяти до тех пор, пока программа не завершится.
Своевременно очищайте сеансы, которые больше не нужны
Для очистки сеансов, которые больше не активны, многие серверы приложений имеют время ожидания сеанса по умолчанию, обычно 30 минут. Когда серверу приложений нужно сохранить больше сессий, если памяти недостаточно, операционная система перенесет часть данных на диск, а сервер приложений также может сбросить некоторые неактивные сессии на диск по алгоритму MRU (самые последние использованные) , Это может даже вызвать исключение нехватки памяти. Если сеанс необходимо сбросить на диск, его необходимо сначала сериализовать, а в крупномасштабных кластерах сериализация объектов обходится дорого. Поэтому, когда сеанс больше не нужен, следует вовремя вызвать метод invalidate() класса HttpSession, чтобы очистить сеанс.
Справочная статья:
Для получения дополнительной информации, пожалуйста, следите за моим личным блогом:Станция Ичжу
Также добро пожаловать на мой общедоступный номер: yizhuxiaozhan, QR-код: