Ответы пользователя по тегу Java
  • Как заставить несколько потоков подождать?

    @nirvimel
    Это можно реализовать через ReentrantReadWriteLock. Управляющий поток захватывает writeLock, а рабочие потоки в точке остановки захватывают readLock (на время какого-то действия, наверное). Они могут захватить readLock все одновременно, но только, если writeLock не захвачен.

    Вообще не знаю зачем вам просто останавливать потоки. Обычно возникает потребность останавливать потоки перед выполнением какого-то действия, которое должно быть защищено. Если у вас просто остановка без защиты следующего за ней действия, то представьте такой вариант:
    1. Блокировка свободна.
    2. Рабочий поток перепрыгивает точку остановки.
    3. Сразу после этого ОС переключает управление на управляющий поток.
    4. Управляющий поток захватывает блокировку.
    5. ОС переключает управление обратно на рабочий поток.
    6. Рабочий поток выполняет код за точкой остановки (блокировка при этом захвачена в управляющем потоке).
    Теперь скажите чем этот результат отличается от того, как если бы рабочий поток просто перепрыгнул бы точку остановки при захваченной блокировке?
    Ответ написан
  • Как пропустить часть кода после выброса исключения в Java?

    @nirvimel
    При размере массива 10 первый цикл for (int i=0; i!=7; i++) проходит без выброса исключений, так как переполнение не достигнуто. А второй for (int i=0; i!=8; i++) выбирает на один элемент больше, в результате происходит underflow (в русском языке, кажется, нет точного аналога этому слову) и вылетает исключение.

    Также вместо if (count > arr.length) должно стоять нестрогое условие if (count >= arr.length). Иначе при count == arr.length в строке arr[count++] будет выход за границы массива.
    Ответ написан
  • Как помешать декомпилировать клиентскую программу?

    @nirvimel
    Смотря какая цель преследуется:
    1. Не дать воспользоваться вашим кодом для создания другого аналогичного продукта.
    2. Скрыть какую-то маленькую "изюминку", которую можно использовать для читерства, если раскопать ее в коде.

    Первое - вполне реально. Стоимость доработки вашего кода без исходников будет намного превышать стоимость создания аналогичного продукта с нуля.
    Второе - нереально в принципе. Не стоит тратить время на это. Потребность в скрытии "изюминок" возникает обычно вследствие ошибочных архитектурных решений (например, проверка на клиенте того, что по-нормальному должно проверяться на сервере) или ошибочных бизнес-моделей.
    Ответ написан
  • Где посмотреть чего состоит IDE Intellij Idea?

    @nirvimel
    На старости лет разработчики IDEA, возможно, напишут об этом мемуары. А пока они зарабатывают деньги на своем продукте, а не на книгах, по которым можно создавать продукты-конкуренты.
    То, что исходники выложены в открытый доступ - это уже очень большая уступка с их стороны (другая контора не пошла бы на такое никогда). От создания конкурирующих продуктов нас останавливает только лень разбираться в чужом коде.
    Ответ написан
  • Как можно оптимизировать изображения без потерь в Java?

    @nirvimel
    Попробую угадать как работает этот TinyJPG:
    1. Берется некоторое начальное значение уровня сжатия (не так важно какое).
    2. Задается некоторый целевой порог допустимых потерь (эта константа предварительно обкатывается в A/B тестах).
    3. На каждом шаге итерации высчитывается среднеквадратическое отклонение значений всех пикселов сжатого изображения (от оригинального), и сравнивается с пороговым знанием.
    4. Бинарным поиском находится минимальное значение уровня сжатия при котором выполняется условие (3).


    Те, кто не заметил разницы в A/B тестах, не заметят разницы и в любых изображениях, сжатых по этому алгоритму.
    Ответ написан
  • Является ли нормальным постоянное создание экземпляров и использование их 1 раз?

    @nirvimel
    Создание временного объекта допустимо (по соображениям производительности), если класс этого объекта удовлетворяет нескольким условиям.
    Временный класс должен иметь только final поля (то есть никаких других полей кроме final он иметь не должен). И сам экземпляр этого класса (если не передается напрямую) должен храниться в final локальной переменной. Если это условие соблюдено (есть еще незначительные условия), то включается крутейшая оптимизация (кажется, начиная с Java 7, но точно не помню), которая на выходе дает код, практически эквивалентный тому, как если бы все поля этого класса передавались бы в функцию через параметры (никакой объект класса при этом не создается).
    Дополнительное условие, требуемое для включения этой оптимизации - код во всех его методах (включая конструктор) не должен вызывать сторонних эффектов (не обращаться к внешним классам, не вызывать new, и др.). Без опыта написания чистых функций проще всего соблюсти это ограничение, если вообще не создавать никаких методов, кроме конструктора, который только инициализирует поля значениями своих параметров.
    Еще одно условие - этот класс должен быть унаследован только от Object и должен запрещать наследование от себя (то есть сам должен быть final).

    Кстати, в последних версиях версиях Java (7/8) вообще много разных оптимизаций для тех, кто пишет final по умолчанию везде, и убирает только когда это совершенно необходимо.
    Ответ написан
  • Как заставить текущий объект перезаписать самого себя?

    @nirvimel
    В режиме телепатии догадываюсь, что вы хотите реализовать. Видимо, речь идет о совершенно стандартном механизме порождения объекта соединения из объекта БД.
    Чтобы понять как строятся подобные велосипеды загляните в код любой ORM или вообще любой ООП-обертки над драйвером БД. Вы увидите в большинстве случаев следующую картину:
    1. Конфигурация БД представляет собой фабрику (да, да, те самые паттерны, которые неофитам НИНУЖНЫ).
    2. Метод connect возвращает объект соединение.
    3. Объект соединение (кроме методов по выполнению запросов) имеет метод close, который закрывает соединение (попытка выполнения запроса на закрытом соединении будет выдавать ошибку).
    4. Соединение (как объект) живет один раз и не может быть переоткрыто после закрытия. Но из фабрики БД всегда можно открыть новое соединение.

    Почему так:
    Главный принцип ООП: отдельному понятию - отдельный класс. БД (на стороне клиента) представляет собой только конфигурацию: адрес сервера, имя юзера, пароль, имя БД и прочие параметры. Соединение к БД - это отдельная сущность, через которую создаются транзакции и курсоры (отдельные сущности), через которые выполняются запросы. Результат выполнения запроса - отдельная сущность. Отдельная строка в выборке - отдельная сущность (если только не кортеж). И только отдельные поля в строке имеют примитивные типы данных.
    Ответ написан
  • Как отобразить изображение по горизонтали без bitmap и matrix?

    @nirvimel
    Если известна ширина по горизонтали, то в каждой строке в цикле переставить пикселы (сколь там у вас байт на пиксел?) в обратном порядке.
    Ответ написан
  • Есть поддержка python библиотек в java?

    @nirvimel
    Можно подцепить libpython через JNI. Но придется писать JNI модуль на Си.
    Если одним языком вам сложно обойтись, то тут не обойдетесь и двумя.
    Ответ написан
  • Можно ли организовать организовать сетевой обмен, через Socket с такими требованиями??

    @nirvimel
    Можно ли организовать организовать сетевой обмен?

    Можно.

    Или как можно организовать такое соединение?

    Для этого понадобится java-программист уровня junior в количестве 1 шт.

    Вообще это похоже на стандартное тестовое задание на собеседовании на вакансию джуниора, которое кандидат обычно пишет на месте в процессе собеседования.
    Ответ написан
  • Как массивы представлены в jvm?

    @nirvimel
    Массивы в JVM вполне настоящие, то есть занимают непрерывное пространство в памяти как на C/C++, то есть реализованы НЕ на списках.
    Операция доступа к элементу массива имеет сложность O(1), а JIT оптимизирует ее до одной машинной инструкции (на x86), то есть так же как доступ к локальной переменной на стеке или полю класса.
    Отдельный элемент массива - не то же самое, что отдельная переменная или поле класса, память, которую он занимает не будет освобождена до тех пор, пока не будет освобожден весь массив.
    Ответ написан
  • Как решить проблему с данной архитектурой Базы данных?

    @nirvimel
    1. Если characteristic_value привязано к subject_model, characteristic_name (почему бы не назваьть эту таблицу просто characteristics, ведь там может храниться еще что-то кроме имени) можно не привязывать к subject. Этим достигается независимость характеристик от субъекта и отсутствие дублей среди характеристик.
    2. Что-бы при назначении значения характеристики модели можно было производить проверку на то, возможна ли вообще такая характеристика для субъекта, нужно ввести кросс-таблицу subject_characteristics (характеристики субъектов), которая бы имела внешние ключи к subject и characteristic_name, то есть many-to-many зависимость между ними, через отдельную кросс-таблицу.
    3. У вас всего два фиксированных уровня иерархии. Что, если на практике потребуется больше? Вы, кажется, стремитесь создать гибкую/универсальную систему. Тогда вам нужна динамическая иерархия категорий.
    4. Если view служит для представления, то внешний ключ к нему в characrteristic_name не нужен, так как логически характеристика, как единица учета, не подчинена представлению данных. Опять же лучше ввести many-to-many зависимость между характеристиками и представлениями, реализованную через кросс-таблицу. Подсистема представлений при этом остается полностью независимой ото основной структуры данных (ее можно убрать не нарушая структуру).


    P.S.: Интересно, в каком это смысле дрель (инструмент) может быть субъектом.
    Ответ написан
  • Где можно найти описание классов java?

    @nirvimel
    В IntelliJ IDEA курсор на интересующий класс/метод и Ctrl+B == все что нужно для глубокого понимания внутренней структуры.
    Ответ написан
  • Сохранение древовидной структуры в файл, best way?

    @nirvimel
    для добавления произвольного узла в дерева, следует пройтись по всем узлам для коррекции смещений узлов в файле и перезаписать.

    Это в любом случае неизбежно. Единственно что можно сделать для сокращения дискового I/O - это, вместо записи множества кусков (через seek->write->seek->write), использовать встроенные в ОС механизм memory mapping (в Java он реализован через MappedByteBuffer), тогда проблема оптимизации кеширования и сброса буферов на диск ложится полностью на ОС.
    Ответ написан
  • Обработка потоков на сервере мессенджера?

    @nirvimel
    Количество потоков не равно количеству открытых сокетов. Расходовать на каждое подключение отдельный поток ни в коем случае нельзя. Но синхронно закрывать сокет после обработки подключения совсем не обязательно. Сокет - просто значение ячейки массива (или карты) будет взято и использовано когда понадобится в любом потоке (работа с конкретным сокетом, конечно, должна быть обернута в соответствующий синхроблок). Единственно, о чем не следует забывать это - KeepAlive пинги (отдельный пул потоков и таймера под них, например), которые обеспечивают сразу две задачи: 1) помогают удержать неактивное соединение (умные роутеры любят закрывать "мертвые" соединения, и клиент, в зависимости от реализации, может делать то же). 2) очищают список сокетов от реально мертвых.
    Ответ написан
  • Почему пишут вот так?

    @nirvimel
    Так делается для того, чтобы оставить за собой возможность впоследствии поменять реализацию не меняя интерфейс. Например, в будущем может потребоваться заменить реализацию ArrayList на LinkedList, если бы в качестве типа переменной был указан конкретный класс, то к тому времени код мог бы уже обрасти различными обращениями к, специфическим для конкретного класса, методами, выходящими за границы интерфейса List. В таком случае при замене реализации на LinkedList пришлось бы выискивать в коде и выкорчевывать оттуда все обращения к специфике ArrayList. На сколько это адски сложная задача знают все, кому приходилось работать над крупными проектами. Поэтому люди, знакомые с этой проблемой, предпочитают предупреждать подобные проблемы заранее, то есть во всех местах, где возможна смена реализации в будущем (то есть почти везде), стараются пользоваться исключительно интерфейсами, вместо того, чтобы опираться на конкретные реализации. В данном примере, если в качестве типа переменной был бы использован интерфейс List, то смена реализации ArrayList на LinkedList решалась бы заменой всего одной строки не зависимо от масштабов проекта.
    Ответ написан