In this talk I’d like to give you an overview of java.util.concurrent package and represent useful Java concurrency tools. I’ll cover the core functionality and the state-of-the-art API (Executors, Accumulators, StampedLock etc).
Simple examples in github (https://github.com/levik666/OverviewInJavaUtilConcurrent)
2. 2CONFIDENTIAL
• Полуков Євген, Software
Engineer у EPAM –
разработчик с более 6
годами опыта в ИТ из них
более 2 лет в EPAM. На
данный момент занимаюсь
разработкой e-commerce
(Hybris).
Обо Мне
6. 6CONFIDENTIAL
Thread : MM
• Каждий поток имет
свой thread stack.
• Вся информация о
методах и их вызовах
сохраняется в thread
stack.
• Все локальные
примитивы
сохраняются thread
stack.
9. 9CONFIDENTIAL
Thread: Visibility of Shared Objects
• Если у нас возникает
работа с общими
объектами без
использования volatile
или synchronization.
• В данном случае нам
помогает volatile
решить данную
проблему.
10. 10CONFIDENTIAL
Thread: Race Conditions
• Гонка потоков при
неатомарных
операциях. Если у нас
возникает работа с
общими объектами без
использование
synchronization.
• В данном случае нам
помогает
synchronization решить
данную проблему.
14. 14CONFIDENTIAL
Executors: ScheduledExecutorService
service = Executors.newSingleThreadScheduledExecutor();
• если требуется отложить выполнение на 5 секунд
service.schedule(()-> { ... }, 5, TimeUnit.SECONDS);
• Если требуется назначить выполнение каждую секунду:
service.scheduleAtFixedRate(() -> { ... }, 0, 1, TimeUnit.SECONDS);
• Eсли требуется назначить выполнение кода с промежутком 1
секунда между выполнениями:
service.scheduleWithFixedDelay(()-> { ... }, 0, 1, TimeUnit.SECONDS);
15. 15CONFIDENTIAL
Accumulators
• Инкрементируем счетчик в
разных потоках.
• Узнать статистику - сколько
потоков имеют доступ к
общему методу.
public void run() {
...
counter.incrementAndGet();
}
public long getCount() {
return counter.get();
}
Что использовать для counter?
17. 17CONFIDENTIAL
Accumulators: LongAdder
• Защита от коллизий за счет структуры и
алгоритма
• @sun.misc.Contended class Cell
• cells: PaddedAtomicLong[availableProcessors()]
• hash: Thread.threadLocalHandonProbe
• Простой API
20. 20CONFIDENTIAL
Accumulators: Atomic Update
• /**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return current;
}
}
36. 36CONFIDENTIAL
Synchronizers : CountDownLatch
• Позволяет одному или нескольким
потокам ожидать до тех пор, пока не
завершится определенное количество
операций, выполняющих в других
потоках.
• Может использоваться раз.
38. 38CONFIDENTIAL
Synchronizers : CountDownLatch
class Service implements Runnable {
private static final int EMULATE_TIME_TO_START = 1000;
private final String name;
private final CountDownLatch latch;
public void run() {
...
sleep(EMULATE_TIME_TO_START);
Logger.getLogger(Service.class.getName()).log(
Level.INFO, name + " is Up");
latch.countDown(); //reduce count of CountDownLatch by 1
}
}
39. 39CONFIDENTIAL
Synchronizers : CountDownLatch
public static void main(String args[]) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(3);
final ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Service(CACHE, latch));
executorService.submit(new Service(ALERT, latch));
executorService.submit(new Service(GSM, latch));
latch.await(); //main thread is waiting on CountDownLatch to finish
Logger.getLogger(Service.class.getName()).log(Level.INFO,
"All services are up, Application is starting now");
}
40. 40CONFIDENTIAL
Synchronizers : CyclicBarrier
• Очень похож на CountDownLatch но при достижение
барьера его можно переиспользовать опять.
• Возможность выполнить дополнительную логику до
достижения барьера.
42. 42CONFIDENTIAL
Synchronizers : Exchanger
• Как видно из названия, основное предназначение
данного класса — это обмен объектами между двумя
потоками.
• При этом, также поддерживаются null значения, что
позволяет использовать данный класс для передачи
только одного объекта или же просто как синхронизатор
двух потоков.
• Первый поток, который вызывает метод exchange(...)
заблокируется до тех пор, пока тот же метод не вызовет
второй поток.
44. 44CONFIDENTIAL
Synchronizers : Exchanger
public static void main(String[] args) {
final Exchanger<String> exchanger = new Exchanger<>();
final ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new SimpleChat(
exchanger, "Неплохо бы завтра в зал. Ну что идем?")
);
executorService.submit(new SimpleChat(
exchanger, "Да настало время жать!!!")
);
executorService.shutdown();
}
45. 45CONFIDENTIAL
Synchronizers : Semaphore
• Используются для ограничения количества потоков при
работе с аппаратными ресурсами или файловой
системой. Доступ к общему ресурсу управляется с
помощью счетчика (permits).
47. 47CONFIDENTIAL
Synchronizers : Резюме
• CountDownLatch
- Делает одноразовую защелку, которую нельзя
обнулить
• CyclicBarrier
- Барьер, который сбрасывается, когда он достигнет
нуля, можна переиспользовать, плюс выполнять
логику, когда барьер достигнут.
• Exchanger
- Предзназначен для обмена объектами между двумя
потоками
48. 48CONFIDENTIAL
Synchronizers : Резюме
• Semaphore
- Предназначен для ограничение количества роботы
потоков в системе. Узким местом при использовании
семафоров является заданное количества разрешений,
т.к. зачастую это число приходится подбирать в
зависимости от мощности «железа».