В повседневной работе не так уж часто приходится сталкиваться с пакетом для многопоточности java.util.concurrent. Иногда существуют проектные ограничения по использованию java 1.4.2, где нет данного пакета, но чаще всего хватает обычной синхронизации и не требуется ничего сверхъестественного. К счастью, периодически возникают задачи, заставляющие немного пораскинуть мозгами и либо написать велосипед, либо порыться в javadoc'ах и найти что-то более подходящее. С велосипедом проблем нет — просто берешь и пишешь, благо ничего суперсложного в многопоточности нет. С другой стороны, меньше кода — меньше багов. Тем более, что на многопоточность никто в здравом уме юнит тестов не пишет, т.к. это уже полноценные интеграционные тесты получаются со всеми вытекающими последствиями.
Что выбрать для конкретного случая? В условиях запарки и deadline'ов довольно сложно охватить весь java.util.concurrent. Выбирается что то похожее и вперед! Так, постепенно, в коде появляются ArrayBlockingQueue, ConcurrentHashMap, AtomicInteger, Collections.synchronizedList(new LinkedList()) и другие интересности. Иногда правильно, иногда нет. В какой то момент времени начинаешь осознавать, что более 95% стандартных классов в java вообще не используются при разработке продукта. Коллекции, примитивы, перекладывание байтиков с одного места на другое, hibernate, spring или EJB, еще какая то библиотека и, вуаля, приложение готово.
Чтобы хоть как то упорядочить знания и облегчить вхождение в тему, ниже идет обзор классов для работы с многопоточностью. Пишу прежде всего как шпаргалку для себя. А если еще кому сгодится — вообще замечательно.
Translate
Показ дописів із міткою thread. Показати всі дописи
Показ дописів із міткою thread. Показати всі дописи
вівторок, 21 травня 2013 р.
понеділок, 20 травня 2013 р.
Five advanced Java Synchronizers you probably don’t know
Besides the common synchronize which is based in the lock bit that every Java object has, you have more sophisticated synchronizers in java, such as:
- Semaphore – Use the concept of a permit to indicate a max number of allowed threads in a place. When you use the value 1, the behavior its similar to synchronize, also called binary semaphore. There is however a big difference here, you acquire a permit on the semaphore, not a locking object,its just a variable to count when a thread acquires a permit and when a thread releases a permit, some kind of a counter. The only thing you really have are threads locking until a permit be available. In the example below, we define 3 as the number of permits, so after 3 acquires the 4 thread will wait for a release before continue its execution.
// Define the semaphore to control 3 permits. // 3 Threads can acquire the mySemaphore Semaphore mySemaphore = new Semaphore(3, true); // 3 threads can execute this line of code. The 4 thread must wait for a release mySemaphore.acquire(); // .. somewhere in the code a thread releases the mySemaphore, // and now the next waiting thread can acquire mySemaphore.release();
четвер, 31 березня 2011 р.
Многопоточность в Java: ExecutorService
В Java 5 было добавлено много вещей для организации многопоточности и особенно касаемо организации параллельного доступа. В этой и последующих статьях мы пройдемся по некоторыми из них.
До Java 5 для организации работы с несколькими потоками приходилось использовать сторонние имплеменации пулинга или писать свой. С появлением
Если требуется использовать кэширующий пул потоков, который создает потоки по мере необходимости, но переиспользует неактивные потоки (и подчищает потоки, которые были неактивные некоторое время), то это задается следующим образом:
Теперь небольшой пример. Допустим, надо запустить какой-нибудь код асинхронно 10 раз. Основываясь на вышесказанном, код будет выглядеть так:
Метод
Иногда требуется выполнение кода асихронно и периодически или требуется выполнить код через некоторое время, тогда на помощь приходит
Например, если требуется отложить выполнение на 5 секунд, потребуется следующий код:
Если требуется назначить выполнение каждую секунду:
И, наконец, если требуется назначить выполнение кода с промежутком 1 секунда между выполнениями:
Взято звідси
ExecutorService
До Java 5 для организации работы с несколькими потоками приходилось использовать сторонние имплеменации пулинга или писать свой. С появлением
ExecutorService такая необходимость отпала.ExecutorService исполняет асинхронный код в одном или нескольких потоках. Создание инстанса ExecutorService'а делается либо вручную через конкретные имплементации (ScheduledThreadPoolExecutor илиThreadPoolExecutor), но проще будет использовать фабрики класса Executors. Например, если надо создать пул с 2мя потоками, то делается это так:ExecutorService service = Executors.newFixedThreadPool(2);Если требуется использовать кэширующий пул потоков, который создает потоки по мере необходимости, но переиспользует неактивные потоки (и подчищает потоки, которые были неактивные некоторое время), то это задается следующим образом:
ExecutorService service = Executors.newCachedThreadPool();Теперь небольшой пример. Допустим, надо запустить какой-нибудь код асинхронно 10 раз. Основываясь на вышесказанном, код будет выглядеть так:
ExecutorService service = Executors.newCachedThreadPool();
for(int i = 0; i < 10; i++) {
service.submit(new Runnable() {
public void run() {
// snip... piece of code
}
});
}Метод
submit также возвращает объект Future, который содержит информацию о статусе исполнения переданного Runnable или Callable (который может возвращать значение). Из него можно узнать выполнился ли переданный код успешно, или он еще выполняется. Вызов метода get на объекте Futureвозвратит значение, который возвращает Callable (или null, если используется Runnable). Метод имеет 2 checked-исключения: InterruptedException, который бросается, когда выполнение прервано через методinterrupt(), или ExecutionException если код в Runnable или Callable бросил RuntimeException, что решает проблему поддержки исключений между потоками.ScheduledExecutorService
Иногда требуется выполнение кода асихронно и периодически или требуется выполнить код через некоторое время, тогда на помощь приходит
ScheduledExecutorService. Он позволяет поставить код выполняться в одном или нескольких потоках и сконфигурировать интервал или время, на которое выполненение будет отложено. Интервалом может быть время между двумя последовательными запусками или время между окончанием одного выполнения и началом другого. Методы ScheduledExecutorServiceвозвращают ScheduledFuture, который также содержит значение отсрочки для выполнения ScheduledFuture.Например, если требуется отложить выполнение на 5 секунд, потребуется следующий код:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.schedule(new Runnable() { ... }, 5, TimeUnit.SECONDS);Если требуется назначить выполнение каждую секунду:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Runnable() { ... }, 0, 1, TimeUnit.SECONDS);И, наконец, если требуется назначить выполнение кода с промежутком 1 секунда между выполнениями:
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(new Runnable() { ... }, 0, 1, TimeUnit.SECONDS);Взято звідси
Підписатися на:
Дописи (Atom)