ThreadPoolExecutor — описать механизм работы, св-ва, частности (fixed threadpool, scheduled, single thread executor)
ThreadPoolExecutor — средство контроля исполнения параллельных задач, задействует один из свободных тредов в общем пуле, или ставит задание в очередь, если таковых нет, или достигнуты определенные условия (ниже)
Основными св-вами ThreadPoolExecutor являются corePoolSize и maxPoolSize. Если текущее количество тредов в пуле < corePoolSize — новый тред будет создаваться в независимости от того, есть ли в пуле незанятые треды. В промежутке между corePoolSize и maxPoolSize тред будет создаваться в том случае, если заполнена очередь задач, и удаляться спустя keepAliveTime. Если кол-во тредов стало >= maxPoolSize — новые треды не создаются, а задачи ставятся в очередь.
Есть возможность регулировать поведение очереди:
• Direct handoffs: немедленная передача задачи тредпулу. Нет понятия очереди задачи. Если свободных тредов нет — кидается exception. Применимо при неограниченных maxPoolSize, но нужно понимать проблему при быстрых записях и медленных чтениях, что может спровоцировать непомерное потребление ресурсов
• Unbounded queues: очередь без ограничений. Задачи будут добавляться в нее при превышении corePoolSize, при этом maxPoolSize будет игнорироваться. Unbounded queues имеют проблемы потребления ресурсов при больших нагрузках, но сглаживают рост тредов при пиках.
• Bounded queues: очередь с ограничениями. Задачи будут добавляться в очередь до достижения некоего capacity. Для достижения наилучшей производительности нужно понимать размеры corePoolSize и самой очереди и чем можно пожертвовать — перфомансом (малый corePoolSize и большая очередь), или же памятью (ограниченная очередь, большой corePoolSize)
Частности ThreadPoolExecutor:
• ScheduleThreadPoolExecutor — применяется для периодичных по времени задач
• fixed thread pool — частность ScheduleThreadPoolExecutor'а с настроенным corePoolSize и unbounded queue
• single thread executor — тредпулл, c сorePoolSize = 1, гарантирующий последовательное выполнение задач из очереди
@javatg
ThreadPoolExecutor — средство контроля исполнения параллельных задач, задействует один из свободных тредов в общем пуле, или ставит задание в очередь, если таковых нет, или достигнуты определенные условия (ниже)
Основными св-вами ThreadPoolExecutor являются corePoolSize и maxPoolSize. Если текущее количество тредов в пуле < corePoolSize — новый тред будет создаваться в независимости от того, есть ли в пуле незанятые треды. В промежутке между corePoolSize и maxPoolSize тред будет создаваться в том случае, если заполнена очередь задач, и удаляться спустя keepAliveTime. Если кол-во тредов стало >= maxPoolSize — новые треды не создаются, а задачи ставятся в очередь.
Есть возможность регулировать поведение очереди:
• Direct handoffs: немедленная передача задачи тредпулу. Нет понятия очереди задачи. Если свободных тредов нет — кидается exception. Применимо при неограниченных maxPoolSize, но нужно понимать проблему при быстрых записях и медленных чтениях, что может спровоцировать непомерное потребление ресурсов
• Unbounded queues: очередь без ограничений. Задачи будут добавляться в нее при превышении corePoolSize, при этом maxPoolSize будет игнорироваться. Unbounded queues имеют проблемы потребления ресурсов при больших нагрузках, но сглаживают рост тредов при пиках.
• Bounded queues: очередь с ограничениями. Задачи будут добавляться в очередь до достижения некоего capacity. Для достижения наилучшей производительности нужно понимать размеры corePoolSize и самой очереди и чем можно пожертвовать — перфомансом (малый corePoolSize и большая очередь), или же памятью (ограниченная очередь, большой corePoolSize)
Частности ThreadPoolExecutor:
• ScheduleThreadPoolExecutor — применяется для периодичных по времени задач
• fixed thread pool — частность ScheduleThreadPoolExecutor'а с настроенным corePoolSize и unbounded queue
• single thread executor — тредпулл, c сorePoolSize = 1, гарантирующий последовательное выполнение задач из очереди
@javatg
SonarQube — платформа для проверки кода на качество по правилам, основанным на соглашениях и стандартах
Инструмент поддерживает 29 языков, в числе которых как ожидаемые Python, Java и C++, так и менее очевидные Cobol и Visual Basic
На первом месте в SonarQube находится измерение качества в соответствии с концепцией технического долга. Он, в свою очередь, вычисляется в долларах и человеко-днях, а также по типам показателей, в процентах
Стоимость: #бесплатно (но есть платные тарифы)
@javatg
Инструмент поддерживает 29 языков, в числе которых как ожидаемые Python, Java и C++, так и менее очевидные Cobol и Visual Basic
На первом месте в SonarQube находится измерение качества в соответствии с концепцией технического долга. Он, в свою очередь, вычисляется в долларах и человеко-днях, а также по типам показателей, в процентах
Стоимость: #бесплатно (но есть платные тарифы)
@javatg
Jivo Mobile SDK позволяет встроить чат в нативные мобильные приложения Android и принимать обращения клиентов. Интеграция занимает несколько минут, так как интерфейс чата с лентой сообщений уже реализован – вам понадобится только добавить несколько строк кода в ваш проект.
- Возможности актуальной версии
- Переписка клиента с оператором
- Отправка файлов в обе стороны
- История переписки клиента с оператором
- Статусы отправки и прочитанности сообщений в чате
- Базовые настройки UI
- Индикатор новых сообщений внутри приложения интегратора
- Push-уведомления
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
☕🛣️ Дорожная карта Java-разработчика в 2023 году: путь с нуля до первой работы
В данной статье мы расскажем, в каком порядке изучать Java, чтобы начать свой путь в разработке и стать востребованным специалистом в 2023 году.
Логическое и алгоритмическое мышление
Один из ключевых навыков для каждого разработчика – логическое и алгоритмическое мышление, которое необходимо развивать на каждом этапе карьеры. Большую часть времени разработчик ищет решения задач или применяет существующие алгоритмы, поэтому очень важно развивать логику и понимание алгоритмов.
➡️ Читать дальше
@javatg
В данной статье мы расскажем, в каком порядке изучать Java, чтобы начать свой путь в разработке и стать востребованным специалистом в 2023 году.
Логическое и алгоритмическое мышление
Один из ключевых навыков для каждого разработчика – логическое и алгоритмическое мышление, которое необходимо развивать на каждом этапе карьеры. Большую часть времени разработчик ищет решения задач или применяет существующие алгоритмы, поэтому очень важно развивать логику и понимание алгоритмов.
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Java в вопросах и ответах: чего ожидать
Собеседование является одним из самых важных действий при трудоустройстве. И не обязательно в качестве программиста на Java/JS. Во время беседы потенциальный работодатель смотрит на соискателя, разговаривает с ним, пытаясь понять, насколько человек подходит для сотрудничества.
В коддинге на Java важно понимать – программера ждут вопросы, ответы на которые определят, насколько грамотен потенциальный работник. Человек, который планирует заниматься разработкой, должен хорошо разбираться в теории. И интервью здесь поможет оценить ситуацию.
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Ответ:
В этой программе мы добавили три элемента в ArrayList и вывели его размер.
Затем мы используем цикл While с итератором. Всякий раз, когда итератор получает следующий элемент, он будет отображать этот элемент, пока мы не достигнем конца списка. В нашем случае это будет повторяться три раза.
Аналогично, мы сделали для улучшенного цикла for, где мы создали объект o для ArrayList с именем testList. Затем вывели на экран значение объекта.
После этого мы создали цикла for, где итератор i установлен сначала на индекс 0, а затем увеличивается на 1 при каждой итерации, пока не будет достигнут предел ArrayList. Наконец, мы выводим на экран каждый элемент, используя метод get(index) для каждой итерации цикла for.
import java.util.*;
public class arrayList {
public static void main(String[] args) {
ArrayList testList = new ArrayList();
testList.add("50");
testList.add("60");
testList.add("70");
System.out.println(testList.size());
System.out.println("Цикл While:");
Iterator iter = testList.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
System.out.println("Улучшенный цикл For:");
for(Object o : testList) {
System.out.println(o);
}
System.out.println("Цикл For:");
for(int i=0; i< testList.size(); i++) {
System.out.println(testList.get(i));
}
}
}
На экране получим:
3
Цикл While:
50
60
70
Улучшенный цикл For:
50
60
70
Цикл For:
50
60
70
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Ответ:
Эти типы программ обычно используются в рамках Selenium framework. Мы добавили подробные комментарии для каждого шага, чтобы сделать программу более понятной.
Логика начинается с того момента, как мы загрузили лист, на котором хранятся данные. Мы пытаемся импортировать электронную почту и пароль. Для этого мы извлекаем ячейку с помощью методов getRow() и getCell(). Допустим, у нас есть электронная почта и пароли в 1-й и 2-й ячейке.
Далее мы устанавливаем тип ячейки - строковой. После этого мы выполняем обычную операцию локатора веб-элемента (By.id), куда мы передали уникальные значения локатора, такие как «email» и «пароль», которые будут идентифицировать эти элементы.
Наконец, мы отправляем ключи, используя element.sendKeys, где cell.getStringCellValue() - это ключ. Эта операция вернет вам значение, сохраненное в ячейках № 1 и 2 соответственно.
@Test
public void ReadData() throws IOException
{
// импортируйте лист Excel из директории web диска c.
//QurentSourceFile – это имя нужного файла excel
File sourceFile=new File("C:\\web\\QurentSourceFile.xls");
// На этом шаге мы загружаем файл. Мы используем FileInputStream для чтения из
// файла excel. В случае если вы хотите проводить запись в файл -
// вам следует использовать FileOutputStream. Путь к файлу передается в качестве
// аргумента FileInputStream
FileInputStream fileInput = new FileInputStream(sourceFile);
// На этом шаге мы загружаем рабочую книгу excel с помощью HSSFWorkbook,
// в который мы передаем fileInput в качестве аргумента
HSSFWorkbook book = new HSSFWorkbook(fileInput);
// На этом шаге мы загружаем конкретный лист excel, на котором хранятся данные.
qurentSheet= book.getSheetAt(0);
for(int i=1; i<= qurentSheet.getLastRowNum(); i++)
{
// Import data for Email.
qurentCell = qurentSheet.getRow(i).getCell(1);
qurentCell.setCellType(Cell.CELL_TYPE_STRING);
driver.findElement(By.id("email")).sendKeys(qurenrCell.getStringCellValue());
// Импортируем данные из ячеек с паролями.
qurentCell = qurentSheet.getRow(i).getCell(2);
qurentCell.setCellType(Cell.CELL_TYPE_STRING);
driver.findElement(By.id("password")).sendKeys(qurenrCell.getStringCellValue());
}
}
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Casting
, или приведение типов — это процесс преобразования одного типа данных в другой тип данных: вручную (неявное приведение) или автоматически (явное приведение типов).Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 16 - 7Автоматическое преобразование выполняет компилятор, а ручное — разработчик.
Приведение типов для примитивов и классов несколько отличается, поэтому и рассмотрим их по отдельности.
Примитивные типы
Пример автоматического приведения примитивных типов:
int value = 17;
double convertedValue = value;
Как видите, никаких дополнительных манипуляций помимо знака = тут не нужно.
Пример ручного приведения примитивных типов:
double value = 17.89;
int convertedValue = (int)value;
В этом случае мы можем наблюдать ручное приведение, которое реализуется с помощью (int), при этом часть за запятой будет отброшена, и convertedValue будет иметь значение - 17.
Подробнее о приведении примитивных типов читайте в этой статье.
Ну а теперь давайте перейдем к объектам.
Ссылочные типы
Для ссылочных типов автоматическое приведение возможно для классов наследников к классам родителям. Это так же называется полиморфизмом.
Предположим, у нас есть класс Lion, который наследуется от класса Cat. В этом случае автоматическое преобразование будет выглядеть так:
Cat cat = new Lion();
А вот с явным приведением всенесколько сложнее, ведь нет функционала обрезания лишнего, как у примитивов.
И сделав просто явно преобразование вида:
Lion lion= (Lion)new Cat();
Вы и получите ошибку:
Разбор вопросов и ответов с собеседований на Java-разработчика. Часть 16 - 8В самом деле, вы можете классу наследнику Lion добавить методы, которых не было изначально в классе Cat, и потом пытаться их вызвать, ведь типа объекта у вас станет Lion. Ну а в этом логики никакой нет.
Поэтому, сужение типа возможно лишь когда изначальный объект типа Lion, но был позже приведен к классу родителя:
Lion lion = new Lion();
Cat cat = lion;
Lion newLion = (Lion)cat;
Также, для большей надежности, сужающее приведение для объектов рекомендуется с использованием конструкции instanceOf:
if (cat instanceof Lion) {
newLion = (Lion)new Cat();
}
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
10 бесплатных курсов по программированию на Java для начинающих в 2023 году
Не тратя больше ваше времени, вот мой список лучших онлайн-курсов для БЕСПЛАТНОГО изучения Java. Я попытался включить различные виды курсов, такие как бесплатные курсы для изучения базовой Java, а также курсы о многопоточности, объектно-ориентированного программирования и т. д.
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Mock-Собеседование на позицию Java Junior Developer. Часть 1.
Mock-Собеседование на позицию Java Junior Developer. Часть 1.
Всем привет, друзья! Выпускаю для вас первую часть собеседования с сильным кандидатом на позицию juinor java разработчика - Феликсом. Сегодня постараемся найти слабые кандидата и проверим его знания…
Всем привет, друзья! Выпускаю для вас первую часть собеседования с сильным кандидатом на позицию juinor java разработчика - Феликсом. Сегодня постараемся найти слабые кандидата и проверим его знания…
Задача:
Реализовать функцию автодополнения следующим образом: по началу слова
необходимо выдавать список из 10 наиболее часто встречающихся слов,
начинающихся с указанного префикса. Сортировать варианты автодополнения в
порядке убывания частоты использования. В случае равенства частот - варианты
сортируются естественным образом (по алфавиту). Если вариантов меньше 10, то
выдавать столько, сколько нашли.
I часть
Решение должно быть в виде консольного java-приложения. Исходные данные
подаются через стандартный поток ввода, а все результаты выводятся в
стандартный поток вывода.
Исходные данные:
В первой строке находится единственное число
N (1 ≤ N ≤ 10^5)
- количество словв словаре. Каждая из следующих N строк содержит слово wi (непустая
последовательность строчных латинских букв длиной не более 15) и целое число
ni (1 ≤ ni ≤ 10^6)
- частота употребления слова wi. Слово и число разделеныединственным пробелом. Ни одно слово не повторяется более одного раза. В
(N+2)-й строке находится число M (
1 ≤ M ≤ 15000)
. В следующих M строкахсодержатся слова uj (непустая последовательность строчных латинских букв
длиной не более 15) - начала слов, введённых пользователем.
Результат:
Для каждой из M строк необходимо вывести наиболее употребляемые слова,
начинающиеся с uj. Варианты дополнения для каждого слова необходимо
разделять переводами строк.
Пример:
stdin
5
kare 10
kanojo 20
karetachi 10
korosu 7
sakura 3
3
k
ka
kar
stdout
kanojo
kare
korosu
karetachi
kanojo
kare
karetachi
kare
karetachi
II часть
Решение должно быть в виде web-приложения с использованием [Spring MVC]
(http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html) и
[AngularJS] (https://angularjs.org/). Запускать приложение на [Apache Tomcat]
(http://tomcat.apache.org/). Исходные данные подаются через файл.
Исходные данные:
В первой строке находится единственное число N
(1 ≤ N ≤ 10^5)
- количество словв словаре. Каждая из следующих N строк содержит слово wi (непустая
последовательность строчных латинских букв длиной не более 15) и целое число
ni
(1 ≤ ni ≤ 10^6)
- частота употребления слова wi. Слово и число разделеныединственным пробелом. Ни одно слово не повторяется более одного раза.
Результат:
На главной странице web-приложения должна быть единственная строка с
вводом. Ввод символов в строку должен сопровождаться выдачей вариантов
автодополнения.
Дополнительные требования:
- Использование [maven] (https://maven.apache.org/) приветствуется (либо
требуется иной скрипт для сборки)
- Код на Java в стиле, соответствующем
рекомендациям http://google.github.io/styleguide/javaguide.html
- Приоритет на скорость работы (решение должно отрабатывать не дольше
1-10 секунд на тестовом файле [test.in]
(https://github.com/dmitryanufriev/kontest/blob/master/test.in))
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача:
Нужно сделать HTTP сервис для сокращения URL наподобие Bitly и других сервисов.
UI не нужен, достаточно сделать JSON API сервис.
Должна быть возможность:
- сохранить короткое представление заданного URL
- перейти по сохраненному ранее короткому представлению и получить redirect на соответствующий исходный URL
Требования:
-Язык программирования: Java
- Предоставить инструкцию по запуску приложения. В идеале (но не обязательно) – использовать контейнеризацию с возможностью запустить проект командой docker-compose up
- Требований к используемым технологиям нет - можно использовать любую БД для персистентности
- Код нужно выложить на github (просьба не делать форк этого репозитория, чтобы не плодить плагиат)
Усложнения:
- Написаны тесты (постарайтесь достичь покрытия в 70% и больше)
- Добавлена валидация URL с проверкой корректности ссылки
- Добавлена возможность задавать кастомные ссылки, чтобы пользователь мог сделать их человекочитаемыми - http://bit.ly/avito-auto-be
- Проведено нагрузочное тестирование с целью понять, какую нагрузку на чтение может выдержать наш сервис
- Если вдруг будет желание, можно слепить простой UI и выложить сервис на бесплатный хостинг - Google Cloud, AWS и подобные.
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Структурированный список ресурсов для изучения Java, который поможет систематизировать занятия. Основан на личном опыте и самостоятельном изучении данной области.
Ставьте ❤️ и отправляйте друзьям
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Напишите метод, который получает на вход Map<K, V> и возвращает Map, где ключи и значения поменяны местами. Так как значения могут совпадать, то тип значения в Map будет уже не K, а
Collection<K>:
Map<V, Collection<K>>
Решение:
public static <K, V> Map<V, Collection<K>> inverse(Map<K, V> map){
Map<V, Collection<K>> resultMap = new HashMap<>();
Set<K> keys = map.keySet();
for(K key : keys){
V value = map.get(key);
resultMap.compute(value, (v, ks) -> {
if(ks == null){
ks = new HashSet<>();
}
ks.add(key);
return ks;
});
}
return resultMap;
}
✔️ Пишите свой вариант в комментариях
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Постройте глубокую копию списка. Глубокая копия должна состоять ровно из n совершенно новых узлов, где каждый новый узел имеет значение равное значению соответствующего ему исходного узла. Оба – следующий и случайный указатель новых узлов – должны указывать на новые узлы в скопированном списке таким образом чтобы указатели и в исходном, и в скопированном списке представляли одно и то же состояние списка. Ни один из указателей в новом списке не должен указывать на узлы в исходном списке.
К примеру, если в исходном списке есть два узла X и Y, где X.random –> Y, то для соответствующих двух узлов x и y в скопированном списке, x.random –> y.
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Парсер SQL запросов
В SQL самым синтаксически сложным и навороченным является, пожалуй, запрос SELECT. Явные и неявные объединения, группировки, подзапросы, сортировки и усечения выборки – вся эта красота может встречаться неоднократно даже в одном единственном select-запросе.
Например, так:
SELECT * FROM book
или так:
SELECT author.name, count(book.id), sum(book.cost)
FROM author
LEFT JOIN book ON (author.id = book.author_id)
GROUP BY author.name
HAVING COUNT(*) > 1 AND SUM(book.cost) > 500
LIMIT 10;
Напишите, пожалуйста, парсер произвольного SELECT-запроса, представляющего его в виде класса примерно такого структуры:
class Query {
private List<String> columns;
private List<Source> fromSources;
private List<Join> joins;
private List<WhereClause> whereClauses;
private List<String> groupByColumns;
private List<Sort> sortColumns;
private Integer limit;
private Integer offset;
}
Структура этого класса не догма, а руководство к действию 🙂 Если вы придумали класс, лучше отражающий структуру SQL-запроса чем приведено здесь – смело используйте свое решение.
Какие конструкции парсер должен поддерживать в обязательном порядке:
- Перечисление полей выборки явно (с алиасами) или *
- Неявное объединение нескольких таблиц (select * from A,B,C)
- Явное объединение таблиц (inner, left, right, full join)
- Фильтрующие условия (where a = 1 and b > 100)
- Подзапросы (select * from (select * from A) a_alias)
- Группировка по одному или нескольким полям (group by)
- Сортировка по одному или нескольким полям (order by)
- Усечение выборки (limit, offset)
На что можно не обращать внимание:
Дополнение выборок (union и union all)
CTE
Window-функции
Немного деталей:
- Выполнять работу необходимо на Kotlin или Java.
- В задании должен быть рабочий метод main(), это должно быть готовое приложение, а не просто библиотека
- По всем вопросам смело писать на [email protected]
- Сделанное задание необходимо разместить на GitHub
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Мы начинаем рубрику решения практических задач на Java с Codewars. Пишите ваши варианты решений в комментариях к посту.
1 Уровень Junior
В маленьком городке население р0 = 1000 в начале года. Население регулярно увеличивается на 2 процента в год, и более 50 новых жителей ежегодно переезжают в город. Сколько лет нужно городу, чтобы его население стало больше или равно p = 1200 жителей?
В конце первого года будет:
1000 + 1000 * 0,02 + 50 => 1070 жителей
В конце 2-го года будет:
1070 + 1070 * 0,02 + 50 => 1141 жителей (** количество жителей — целое число **)
В конце 3-го года будет:
1141 + 1141 * 0,02 + 50 => 1213
На это потребуется целых 3 года.
Более общие параметры:
p0, процент, aug (жители приезжащие или уезжающие каждый год), p (население)
функция nb_year должна возвращать n полных лет, необходимых для получения населения, большего или равного p.
aug — целое число, процент — положительное число, p0 и p — положительные целые числа (> 0)
Пример
nb_year(1500, 5, 100, 5000) -> 15
nb_year(1500000, 2.5, 10000, 2000000) -> 10
Примечание:
Не забудьте преобразовать результаты процент в вашей функции: если выводравен 2, вы должны преобразовать его в 0,02.
Ответ:
public class GrowthOfAPopulation {
public static int nbYear(int p0, double percent, int aug, int p) {
int years = 0;
int inhabitants = p0;
while(inhabitants < p)
{
inhabitants = (int)(inhabitants + (inhabitants * (float)(percent/100)) + aug);
years++;
}
return years;
}
}
@javatg
Please open Telegram to view this post
VIEW IN TELEGRAM