Но не сказали, чем плоха предложенная мной конструкция.
С моей точки зрения, ответ простой. Для того, чтобы её использовать придётся затащить в язык goto, который в большинстве случаев оказывается вредным. И по итогу легче вообще убрать goto, чем следить за тем, как его использовать.
У goto я лично знаю два кейса удачного применения. Переход к концу метода в случае возникновения ошики, и тот, что продемонстрировали вы.
Первое решается введением в язык эксепшнов.
Ваш кейс, по крайней мере в джаве, будет выглядеть вот так
label:
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (get(i,j)) {
break label;
}
}
}
goto убрали, а полезные функции раздали другим конструкциям
Просто ваше утверждение, что 1 поток на 2 сокета справится с задачей пересылки быстрее, чем 2 потока на 2 сокета сильно интригующе и противоречит всему тому, что я читал 10 лет и моему здравому смыслу.
Если один поток обрабатывает 2 сокета, то на обработку одного секта уйдёт больше времени, чем если бы один поток работал с одним сокетом. Потому что какое-то время поток работает с другим сокетом. Это увеличивает latency.
Но суммарно на обработку двух сокетов уйдёт меньше времени, потому что пересылка данных для обоих сокетов происходит параллельно. Это увеличивает throughput.
Если мы сравниваем 1 поток обрабатывающий 2 сокета с двумя потоками, обрабатывающими 2 сокета, то latency у двух потоков будет чуть меньше, throughput будет чуть больше, но также вырастет количество используемого CPU и чуть чуть количество оперативной памяти.
Неблокирующие техники используются как раз для того, чтобы сильно сократить использование CPU и памяти при равном throughput с несущественным увеличением latency.
Насколько я помню, nio — не о throughput, а о scalability.
Ну тут именно о throughput.
Ссылок на бенчмарки сейчас по памяти не приведу, но, как минимум, переключение контекстов должно добавлять накладных расходов.
Если количество одновременных запросов больше количества потоков, то пропускная спосоность увеличивается, хотя каждый отдельный запрос может обрабатываться дольше. Как раз за счёт переключения контекстов в том числе.
Но вообще ожидание ответа или ожидание данных после установки соединения это очень долго. За это время можно успеть пару раз переключить контекст и сообщить другим соединениям, что они могут отправлять данные. И потом ещё какие-нибудь данные, полученные из третьего соединения обработать. А потом вернуться к первому соединению и проверить, пришло ли в него что-нибудь.
Да и не просто так однопоточный gc показывает более высокий именно throughput.
Не просто так, да. Потому что он специально останавливает всё, чтобы ничего не ждать, а просто перемолотить все объекты.
Зачем код простаивает после ожидания ответа (или во время?) и перед обработкой?
Программист специально так написал код. Только простававет не код, а поток в котором код исполняется.
Если хотите поискать в этом практический смысл, то когда поток ждёт ответа, он гарантировано будет не занять, когда ответ придёт и сразу сможет обработать ответ. И поэтому время на обработку одного запроса будет чуть меньше. Если количество одновременно обрабатываемых запросов всегда меньше максимального количества потоков, то такой код будет работать чуть быстрее, чем код, который не ждёт ответа.
Разве поток не может отправить другой запрос вместо простаивания?
Может, но код надо писать по другому.
Дополню, я не настоящий jav'ист, в java нельзя отправлять асинхронные запросы?
И dexamethason. Как я понял это были 2 маленькие таблетки которые мне дали вечером и в 10 утра следующего дня.
Интересно. В наших больницах дексаметазон капают через капельницу. Говорят по другому малоэффективен. Мне кололи его внутримышечно дней 6, состояние ухудшилось. После пары дней под капельницей стало лучше.
Очень ёмкие вопросы в комментарии, по поводу каждого статью наверное можно забабахать. Отвечу кратко на, с моей точки зрения, самый важный. Можно ли устроиться джуниором после курсов.
Вопрос непростой.
Да, джуниором устроиться можно, но требования к начинающему разработчику сильно зависят от компании и проекта. Мы готовим людей к разработке бекенда с использованием Spring. Компаний, использующих такой стек много, тут всё хорошо.
Кроме стека, у компании должно быть чёткое понимание, какие задачи она хочет поставить перед новым разработчиком. Если компания ищет разработчика просто на всякий случай, то скорее всего набирать будут мидлов.
И нужен ещё старший программист, который готов отвечать на вопросы, которые обязательно появятся у джуниора.
Под такое описание обычно подходят стартапы или какие-то продуктовые компании, в которых не хватает рабочих рук. Сейчас такие компании на рынке есть, главное каким-то образом обратить на себя их внимание. Придётся рассылать резюме, проходить собеседования и ждать отзывов, которые не каждая контора ещё даст. Но перспективы реальные, месяц назад по крайней мере один такой джуниор работу нашёл, с интересом за ним наблюдаю ))
Однако есть одно но. Мне в последнее время говорят, что надо всё объяснять с помощью аналогий, иначе непонятно, поэтому вот держите аналогию из мира спорта.
Когда поднимаешь тяжести, есть две составляющих успеха. Во-первых, техника. Если поднимать тяжести правильно, то результаты появятся гораздо быстрее, чем если заниматься этим как-попало.
Но если ограничиться теоретическими занятиями и отработкой техники на пустом грифе, то результат не появится никогда.
Тренер может рассказать как делать правильно. Может посмотреть, что делаете вы и дать оценку. Но для того, чтобы были результаты, нужно регулярно заниматься в тренажёрном зале. Самому. Тут тренер ничего не сделает, этим вам придётся заниматься самостоятельно.
И важно отметить, что продвинутые техники может изучить только человек, у которого уже есть какое-то минимальное количество мышечной массы, это важно.
Так и с программированием. Первые занятия у всех идут хорошо. С помощью домашних заданий мы можем проверить, поняли учащиеся материал, или нет. Но чтобы делать домашние задания для следующих занятий, нужно свободно владеть приёмами, описанными на предыдущих. Многим для этого придёся прорешать задачи дополнительно. И за них это никто не сделает.
Когда вам будут рассказывать про паттерны, это будут делать на примере кода. И нужно хорошо понимать, как работает этот код и что делает. Достичь такого понимания можно только одним способом. Писать код самостоятельно. И позже читать чужой код.
К собеседованиям тоже придётся готовиться. Если вы понимаете, как устроен динамический массив, но не можете об этом рассказать, то с точки зрения работодателя это всё равно как если вы вообще не знаете, что это такое. Придётся тренироваться отвечать перед зеркалом.
Поэтому ещё раз скажу, устроиться джуниором реально, но очень многое зависит от вас.
P. S. В роли наставника я увы, сейчас выступать не могу, курс постоянно корректируется на основе обратной связи, на это много времени уходит. Если хочется пообщаться именно со мной, пишите в личку, я обязательно отвечу.
Кому станет хуже от того, что юзер станет чаще выигрывать?
Ну как же. Тому программисту, который написал такой код, что юзер выигрывает редко )). В потом уже другой программист, которого наняли, чтобы поправить код предыдущего, переживал по этому же поводу.
Больше похоже на таракан, чем на профессиональную этику.
Таракан, да, но по мнению некоторых, такие тараканы отличают хороших программистов от идеальных ))
Это не мой некропостинг, просто кто-то прокрастинировал с одобрением комментария пять лет.
Да, я очень удивился. Не мог отказать себе в удовольствии ответить )))
цель подобных курсов всегда одна — заработать денег.
Как в общем и цель любого бизнеса )). Но как правило, когда речь о курсах, заработать денег получается только если бизнес выполняет свои обещания и курсы взаправду дают знания и скилы.
не знания продать. не научить за оплату. а именно — заработать денег.
Отдельно хочу сказать за себя. Я тут именно для того, чтобы научить программировать тех, кто этого хочет. Вопрос денег лично у меня вторичен. Мне неоднократно говорили, что это нездоровая позиция, возможно я её перерасту когда-нибудь, но пока что вот так.
за два три месяца плотных занятий, по 6...8 часов каждый день — можно выйти на уверенного джуна. и что там растягивать на 11 месяцев ??
Совершенно согласен, можно. Хотя я бы, конечно, слово максимум убрал бы )). Если есть желание и силы впахивать по 6...8 часов каждый день в течении трёх месяцев, то можно. Особенно, если готовишься к конкретной позиции в конкретной компании. Я даже знаю случаи.
Мне особенно приятно читать ваш комментарий потому, что зачастую я сталкиваюсь с обратной позицией — что для того, чтобы стать джуниором и трёх лет не всегда хватает.
Но на курсы приходят люди, которые каждый день работают и у которых полный день найдётся только на выходных и это в лучшем случае. Вот из-за этого получается 11 месяцев.
основная проблема таких курсов в том, что они обещают "очень вкусное" но трудно выполнимое. научить "для людей без бэкграунда в IT". почему же трудно выполнимое? да потому, что далеко не всем это реально интересно и нужно.
Сложно поспорить, всё именно так и есть. Именно поэтому я всегда повторяю, что ничего невозможного нет, нужно только желание и труд. Только желание по-настоящему нужно и трудиться действительно придётся. Это очень важно осознавать.
Вы прячете в деталь реализации неожиданное усложнение .get из мапы до o(n).
Поэтому не надо делать энтити ключами мапы
Пишем типовой поиск всех элементов из соседней коллекции в этой и вот он квадрат.
По перечисленным выше причинам, так делать не надо.
И уже не надо много. Уже тысячах на 10 элементов тормоза будут.
Во-первых, по перечисленным выше причинам на надо делать Set из десяти тысяч энтити. Потому что это приведёт к проблемам.
Во-вторых, десять тысяч элементов на связи OneToMany это много независимо от коллекции, которая используется для их хранения. В таких случаях лучше делать только связь ManyToOne потом выбирать элементы отдельным запросом.
Не надо так софт проектировать.
Я тоже говорю об этом.
Не надо использовать энтити в качестве ключей хешмепа. Не надо использовать что-то кроме id в equals и hashCode. hashCode должен возвращать константу. equals должен вернуть false если хотя бы один id равен null. Это актуально для энтити в которых нет естественного ключа, а суррогатный ключ не известен сразу после вызова конструктора объекта.
Не надо делать OneToMany с большим количеством участников. Это актуально для всех энтити.
Правил ещё много, но эти относятся к теме напрямую.
Врядли нас обманывают ))). Я делюсь своим опытом, комментаторы своим. Мне кажется имеет смысл верить, что по крайней мере субъективно у них и правда всё получается понятно и код нормально читается другими людьми
Практикующие такое утверждают, что понятно всем. Я, правда, не поддерживаю эту позицию. Лично я считаю, что надо рефакторить код по мере возникновения вопросов по нему. Как не избегай состояния потока, всё равно ты при разработке периодически в него попадаешь.
Прошу прощения за недостаточную детализацию. Если серьёзно писать на эту тему — комментария не хватит. И вот эту важную деталь, как и многие другие, я не упомянул. Использование коллекций с JPA вообще нетривиальная штука. Мало того, что в некторых случаях надо делать remove а потом add одного и того же объекта, так ещё и надо делать много странных движений для маппинга, если хочешь убрать дополнительные запросы. Плюс надо помнить, что в Hibernate зачастую используется на ArrayList или что-то в этому духе, а какая-нибудь другая структура. Когда я пытаюсь вкратце рассказать, постоянно что-то упускаю.
Это просто особенность реализации HashSet и TreeSet.
Контракт на интерфейс Set гарантирует, что если сделать сначала remove, а потом add, то в коллекции окажется новый объект. Наверное надо было сразу написать про все операции целиком.
По хорошему движок JPA не должен поместить в контекст две разных энтити, указывающих на одну и ту же строку. Вся штука в том, что нужно держать в одной коллекции несколько энтити, которые есть в контексте, которых ещё в нём нет и не забыть про энтити, которые пока не попали даже в БД.
С моей точки зрения, ответ простой. Для того, чтобы её использовать придётся затащить в язык goto, который в большинстве случаев оказывается вредным. И по итогу легче вообще убрать goto, чем следить за тем, как его использовать.
У goto я лично знаю два кейса удачного применения. Переход к концу метода в случае возникновения ошики, и тот, что продемонстрировали вы.
Первое решается введением в язык эксепшнов.
Ваш кейс, по крайней мере в джаве, будет выглядеть вот так
goto убрали, а полезные функции раздали другим конструкциям
Завернуть в метод и написать return
Если один поток обрабатывает 2 сокета, то на обработку одного секта уйдёт больше времени, чем если бы один поток работал с одним сокетом. Потому что какое-то время поток работает с другим сокетом. Это увеличивает latency.
Но суммарно на обработку двух сокетов уйдёт меньше времени, потому что пересылка данных для обоих сокетов происходит параллельно. Это увеличивает throughput.
Если мы сравниваем 1 поток обрабатывающий 2 сокета с двумя потоками, обрабатывающими 2 сокета, то latency у двух потоков будет чуть меньше, throughput будет чуть больше, но также вырастет количество используемого CPU и чуть чуть количество оперативной памяти.
Неблокирующие техники используются как раз для того, чтобы сильно сократить использование CPU и памяти при равном throughput с несущественным увеличением latency.
Ну тут именно о throughput.
Если количество одновременных запросов больше количества потоков, то пропускная спосоность увеличивается, хотя каждый отдельный запрос может обрабатываться дольше. Как раз за счёт переключения контекстов в том числе.
Но вообще ожидание ответа или ожидание данных после установки соединения это очень долго. За это время можно успеть пару раз переключить контекст и сообщить другим соединениям, что они могут отправлять данные. И потом ещё какие-нибудь данные, полученные из третьего соединения обработать. А потом вернуться к первому соединению и проверить, пришло ли в него что-нибудь.
Не просто так, да. Потому что он специально останавливает всё, чтобы ничего не ждать, а просто перемолотить все объекты.
Программист специально так написал код. Только простававет не код, а поток в котором код исполняется.
Если хотите поискать в этом практический смысл, то когда поток ждёт ответа, он гарантировано будет не занять, когда ответ придёт и сразу сможет обработать ответ. И поэтому время на обработку одного запроса будет чуть меньше. Если количество одновременно обрабатываемых запросов всегда меньше максимального количества потоков, то такой код будет работать чуть быстрее, чем код, который не ждёт ответа.
Может, но код надо писать по другому.
Можно.
Интересно. В наших больницах дексаметазон капают через капельницу. Говорят по другому малоэффективен. Мне кололи его внутримышечно дней 6, состояние ухудшилось. После пары дней под капельницей стало лучше.
Очень ёмкие вопросы в комментарии, по поводу каждого статью наверное можно забабахать. Отвечу кратко на, с моей точки зрения, самый важный. Можно ли устроиться джуниором после курсов.
Вопрос непростой.
Да, джуниором устроиться можно, но требования к начинающему разработчику сильно зависят от компании и проекта. Мы готовим людей к разработке бекенда с использованием Spring. Компаний, использующих такой стек много, тут всё хорошо.
Кроме стека, у компании должно быть чёткое понимание, какие задачи она хочет поставить перед новым разработчиком. Если компания ищет разработчика просто на всякий случай, то скорее всего набирать будут мидлов.
И нужен ещё старший программист, который готов отвечать на вопросы, которые обязательно появятся у джуниора.
Под такое описание обычно подходят стартапы или какие-то продуктовые компании, в которых не хватает рабочих рук. Сейчас такие компании на рынке есть, главное каким-то образом обратить на себя их внимание. Придётся рассылать резюме, проходить собеседования и ждать отзывов, которые не каждая контора ещё даст. Но перспективы реальные, месяц назад по крайней мере один такой джуниор работу нашёл, с интересом за ним наблюдаю ))
Однако есть одно но. Мне в последнее время говорят, что надо всё объяснять с помощью аналогий, иначе непонятно, поэтому вот держите аналогию из мира спорта.
Когда поднимаешь тяжести, есть две составляющих успеха. Во-первых, техника. Если поднимать тяжести правильно, то результаты появятся гораздо быстрее, чем если заниматься этим как-попало.
Но если ограничиться теоретическими занятиями и отработкой техники на пустом грифе, то результат не появится никогда.
Тренер может рассказать как делать правильно. Может посмотреть, что делаете вы и дать оценку. Но для того, чтобы были результаты, нужно регулярно заниматься в тренажёрном зале. Самому. Тут тренер ничего не сделает, этим вам придётся заниматься самостоятельно.
И важно отметить, что продвинутые техники может изучить только человек, у которого уже есть какое-то минимальное количество мышечной массы, это важно.
Так и с программированием. Первые занятия у всех идут хорошо. С помощью домашних заданий мы можем проверить, поняли учащиеся материал, или нет. Но чтобы делать домашние задания для следующих занятий, нужно свободно владеть приёмами, описанными на предыдущих. Многим для этого придёся прорешать задачи дополнительно. И за них это никто не сделает.
Когда вам будут рассказывать про паттерны, это будут делать на примере кода. И нужно хорошо понимать, как работает этот код и что делает. Достичь такого понимания можно только одним способом. Писать код самостоятельно. И позже читать чужой код.
К собеседованиям тоже придётся готовиться. Если вы понимаете, как устроен динамический массив, но не можете об этом рассказать, то с точки зрения работодателя это всё равно как если вы вообще не знаете, что это такое. Придётся тренироваться отвечать перед зеркалом.
Поэтому ещё раз скажу, устроиться джуниором реально, но очень многое зависит от вас.
P. S. В роли наставника я увы, сейчас выступать не могу, курс постоянно корректируется на основе обратной связи, на это много времени уходит. Если хочется пообщаться именно со мной, пишите в личку, я обязательно отвечу.
Ну как же. Тому программисту, который написал такой код, что юзер выигрывает редко )). В потом уже другой программист, которого наняли, чтобы поправить код предыдущего, переживал по этому же поводу.
Таракан, да, но по мнению некоторых, такие тараканы отличают хороших программистов от идеальных ))
Да, я очень удивился. Не мог отказать себе в удовольствии ответить )))
Как в общем и цель любого бизнеса )). Но как правило, когда речь о курсах, заработать денег получается только если бизнес выполняет свои обещания и курсы взаправду дают знания и скилы.
Отдельно хочу сказать за себя. Я тут именно для того, чтобы научить программировать тех, кто этого хочет. Вопрос денег лично у меня вторичен. Мне неоднократно говорили, что это нездоровая позиция, возможно я её перерасту когда-нибудь, но пока что вот так.
Совершенно согласен, можно. Хотя я бы, конечно, слово максимум убрал бы )). Если есть желание и силы впахивать по 6...8 часов каждый день в течении трёх месяцев, то можно. Особенно, если готовишься к конкретной позиции в конкретной компании. Я даже знаю случаи.
Мне особенно приятно читать ваш комментарий потому, что зачастую я сталкиваюсь с обратной позицией — что для того, чтобы стать джуниором и трёх лет не всегда хватает.
Но на курсы приходят люди, которые каждый день работают и у которых полный день найдётся только на выходных и это в лучшем случае. Вот из-за этого получается 11 месяцев.
Сложно поспорить, всё именно так и есть. Именно поэтому я всегда повторяю, что ничего невозможного нет, нужно только желание и труд. Только желание по-настоящему нужно и трудиться действительно придётся. Это очень важно осознавать.
Поэтому не надо делать энтити ключами мапы
По перечисленным выше причинам, так делать не надо.
Во-первых, по перечисленным выше причинам на надо делать Set из десяти тысяч энтити. Потому что это приведёт к проблемам.
Во-вторых, десять тысяч элементов на связи OneToMany это много независимо от коллекции, которая используется для их хранения. В таких случаях лучше делать только связь ManyToOne потом выбирать элементы отдельным запросом.
Я тоже говорю об этом.
Не надо использовать энтити в качестве ключей хешмепа. Не надо использовать что-то кроме id в equals и hashCode. hashCode должен возвращать константу. equals должен вернуть false если хотя бы один id равен null. Это актуально для энтити в которых нет естественного ключа, а суррогатный ключ не известен сразу после вызова конструктора объекта.
Не надо делать OneToMany с большим количеством участников. Это актуально для всех энтити.
Правил ещё много, но эти относятся к теме напрямую.
Врядли нас обманывают ))). Я делюсь своим опытом, комментаторы своим. Мне кажется имеет смысл верить, что по крайней мере субъективно у них и правда всё получается понятно и код нормально читается другими людьми
Практикующие такое утверждают, что понятно всем. Я, правда, не поддерживаю эту позицию. Лично я считаю, что надо рефакторить код по мере возникновения вопросов по нему. Как не избегай состояния потока, всё равно ты при разработке периодически в него попадаешь.
Прошу прощения за недостаточную детализацию. Если серьёзно писать на эту тему — комментария не хватит. И вот эту важную деталь, как и многие другие, я не упомянул. Использование коллекций с JPA вообще нетривиальная штука. Мало того, что в некторых случаях надо делать remove а потом add одного и того же объекта, так ещё и надо делать много странных движений для маппинга, если хочешь убрать дополнительные запросы. Плюс надо помнить, что в Hibernate зачастую используется на ArrayList или что-то в этому духе, а какая-нибудь другая структура. Когда я пытаюсь вкратце рассказать, постоянно что-то упускаю.
Контракт на интерфейс Set гарантирует, что если сделать сначала remove, а потом add, то в коллекции окажется новый объект. Наверное надо было сразу написать про все операции целиком.
Мне кажется нет такого. Какое поведение из того на что я ссылаюсь не документировано?
Именно для того, чтобы объект не менял бакет, hashCode должен возвращать константу
По хорошему движок JPA не должен поместить в контекст две разных энтити, указывающих на одну и ту же строку. Вся штука в том, что нужно держать в одной коллекции несколько энтити, которые есть в контексте, которых ещё в нём нет и не забыть про энтити, которые пока не попали даже в БД.
Чтобы когда кладёшь в Set энтити и там уже есть энтити с таким id, новая энтити вытеснила старую.
Ну и иногда удобно делать arrayList.contains
Ну вот я и говорю, что дерево будет в лучшем случае ))
Если переопределить equals, то проблем с определением быть не должно, даже если одна из сущностей ещё не находится в контексте.