SlideShare une entreprise Scribd logo
1  sur  89
Приёмы параллельного
программирования в Java
Виды параллельных вычислений


Распараллеливание вычислений может быть на уровне:
 систем (распределенные системы, облачные вычисления, grid, cluster, etc.)
 процессов (процессы ОС)
 потоков


Взаимодействие потоков выполнения может быть через:
 общую память
 общее хранилище данных (базу данных)




Page  2
Мотивация


 Увеличение производительности за счет равномерного использования
  нескольких процессоров или разнородных систем:
  – Обработка больших объемов данных
    (Построение отчетов, бизнес аналитика, индексирование больших хранилищ)
  – Долгие вычисления
    (Шифрование, переборные алгоритмы (расчет маршрутов, минимизация
    издержек, решение математических задач, игры и т.д.)


 Масштабируемость системы (если эффективно распараллеливается –
  можно задействовать больше машин)




Page  3
                                                                       3
Мотивация


Может исходить из функциональных требований к системе, например:
   Система должна быть многопользовательской
   Многозадачность
   Выполнение каких-либо действий в фоновом режиме или асинхронно
   Выполнение каких-либо действий по расписанию
   Отзывчивый пользовательский интерфейс




Page  4
                                                               4
Подходы к распараллеливанию вычислений


 Разделяемый доступ к общей памяти
  – блокировки, синхронизация критических секций, барьеры памяти, атомарные
    инструкции типа CAS, базы данных, транзакции
 Обмен сообщениями
  – Erlang (модель акторов), Occam (CSP) – потоки не имеют доступа к общей памяти,
    но могут обмениться сообщениями синхронно или асинхронно
  – Можно реализовать и в Java с использованием Immutable типов, глубокого
    копирования данных и обмена сообщениями (например JMS)
 Полная изолированность потоков вычислений (Одни потоки могут
  порождать другие при этом передавая на вход данные. Поток обрабатывает
  исходные данные и возвращает результат породившему потоку)
  – MapReduce (AppEngine Mapper API, Apache Hadoop),
  – J2EE WorkManager

Page  5
Возникающие проблемы


 Разделяемый доступ к общей памяти
  – Сохранение целостности данных при одновременном доступе (thread-safety),
       • непредсказуемость фактического порядка исполнения инструкций (race
         conditions)
  – Конечность вычислений
       • взаимная блокировка потоков (deadlock)
       • зависание потока (starvation)
       • тупиковая ситуация (livelock)
       • инверсия приоритетов (priority inversion)
  – Низкая производительность
       • ожидание очереди на блокировку
       • переключение контекста (context switching)

Page  6
Плюсы и минусы подходов


 Обмен сообщениями
  – код всегда потокобезопасен
  – легче масштабировать
  – дополнительные затраты на коммуникации
  – сложнее строить алгоритмы


 Изолированные потоки
  – сложность алгоритмического распараллеливания обработки данных
  – легко масштабируется
  – нет всех вышеперечисленных проблем




Page  7
Взаимная блокировка




Page  8
Граф блокировок потоков




                              B
              А



                                  E


                          D
              C




Page  9
Взаимная блокировка.

            final Object lockA = new Object();
            final Object lockB = new Object();
            new Thread() {
                         public void run() {
                                   synchronized (lockA) {
                                               synchronized (lockB) {
                                                         // Do something
                                               }
                                   }
                         }
            }.start();
            new Thread() {
                         public void run() {
                                   synchronized (lockB) {
                                               synchronized (lockA) {
                                                         // Do something
                                               }
                                   }
                         }
            }.start();


Page  10
Дамп потоков


Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode):


"Thread-1" prio=6 tid=0x0000000006998800 nid=0x1a48 waiting for monitor entry [0x00000000076af000]
 java.lang.Thread.State: BLOCKED (on object monitor)
            at DeadlockDemo$2.run(DeadlockDemo.java:27)
            - waiting to lock <0x00000007d5d0a6e8> (a java.lang.Object)
            - locked <0x00000007d5d0a6f8> (a java.lang.Object)


"Thread-0" prio=6 tid=0x0000000006998000 nid=0x1620 waiting for monitor entry [0x000000000748f000]
 java.lang.Thread.State: BLOCKED (on object monitor)
            at DeadlockDemo$1.run(DeadlockDemo.java:16)
            - waiting to lock <0x00000007d5d0a6f8> (a java.lang.Object)
            - locked <0x00000007d5d0a6e8> (a java.lang.Object)
…




Page  11
Вывод информации о блокировках

Found one Java-level deadlock:
=============================
"Thread-1":
 waiting to lock monitor 0x000000000058ca80 (object 0x00000007d5d0a6e8, a java.lang.Object),
 which is held by "Thread-0"
"Thread-0":
 waiting to lock monitor 0x000000000058f330 (object 0x00000007d5d0a6f8, a java.lang.Object),
 which is held by "Thread-1"


Java stack information for the threads listed above:
===================================================
"Thread-1":
              at DeadlockDemo$2.run(DeadlockDemo.java:27)
              - waiting to lock <0x00000007d5d0a6e8> (a java.lang.Object)
              - locked <0x00000007d5d0a6f8> (a java.lang.Object)
"Thread-0":
              at DeadlockDemo$1.run(DeadlockDemo.java:16)
              - waiting to lock <0x00000007d5d0a6f8> (a java.lang.Object)
              - locked <0x00000007d5d0a6e8> (a java.lang.Object)


Found 1 deadlock.
Page  12
Взаимная блокировка взаимодействующих объектов

class A {
             public synchronized void callB(B b){
                       b.process();
             }
             public synchronized void process(){}
}
class B {
             public synchronized void callA(A a){
                       a.process();
             }
             public synchronized void process(){}
}


final A a = new A();
final B b = new B();


//Thread1
a.callB(b);


//Thread 2
b.callA(a);
Page  13
Дамп потоков


"Thread-1" prio=6 tid=0x0000000006ab1000 nid=0x18a8 waiting for monitor entry [0x00000000076ef000]
 java.lang.Thread.State: BLOCKED (on object monitor)
            at DeadlockDemo1$A.process(DeadlockDemo1.java:16)
            - waiting to lock <0x00000007d5d0bac0> (a DeadlockDemo1$A)
            at DeadlockDemo1$B.callA(DeadlockDemo1.java:26)
            - locked <0x00000007d5d0cc30> (a DeadlockDemo1$B)
            at DeadlockDemo1$2.run(DeadlockDemo1.java:45)


"Thread-0" prio=6 tid=0x0000000006ab0000 nid=0x17e0 waiting for monitor entry [0x00000000075ef000]
 java.lang.Thread.State: BLOCKED (on object monitor)
            at DeadlockDemo1$B.process(DeadlockDemo1.java:31)
            - waiting to lock <0x00000007d5d0cc30> (a DeadlockDemo1$B)
            at DeadlockDemo1$A.callB(DeadlockDemo1.java:11)
            - locked <0x00000007d5d0bac0> (a DeadlockDemo1$A)
            at DeadlockDemo1$1.run(DeadlockDemo1.java:39)


Page  14
Случай c аппаратом лучевой терапии Therac-25


Этот аппарат работал в трёх режимах:
 Электронная терапия: электронная пушка напрямую облучает пациента;
  компьютер задаёт энергию электронов от 5 до 25 МэВ.
 Рентгеновская терапия: электронная пушка
  облучает вольфрамовую мишень, и пациент облучается рентгеновскими
  лучами, проходящими через конусообразный рассеиватель. В этом режиме
  энергия электронов одна: 25 МэВ.
 В третьем режиме никакого излучения не было. На пути электронов (на
  случай аварии) располагается стальной отражатель, а излучение
  имитируется светом. Этот режим применяется для того, чтобы точно
  навести пучок на больное место.




Page  15
Модель памяти Java. Зачем это нужно знать?

public class NoVisibility {
            private static boolean ready;
            private static int number;


            private static class ReaderThread extends Thread {
                     public void run() {
                              while (!ready)
                                       Thread.yield();
                              System.out.println(number);
                     }
            }


            public static void main(String[] args) {
                     new ReaderThread().start();
                     number = 42;
                     ready = true;
            }
}
Page  16
Модель памяти Java



Что это?
Это часть спецификации языка Java (JLS chapter 17), описывающая на
низком уровне принципы хранения переменных в памяти (полей
объекта, класса, элементов массива и т.д.) и доступа потоков к общей памяти.


Описывает поведение многопоточных программ в терминах:
 Атомарности операций
 Видимости данных
 Порядка выполнения инструкций




Page  17
Модель памяти Java. Атомарность операций


Какие операции являются атомарными?
Атомарные операции – эффект которых на систему семантически такой же
как если бы они выполнялись мгновенно и результат не зависел от работы
других потоков.
Согласно модели памяти Java:
  – Чтение и запись значений в память соответствующую переменной (кроме типов
    long и double) является атомарной операцией
  – Чтение и запись указателей атомарно вне зависимости от разрядности указателя
    (32 или 64 бита)
  – Чтение и запись volatile long или double переменных атомарно




Page  18
Модель памяти Java. Видимость данных

Видимость данных - это правила, описывающие при каких обстоятельствах
изменение переменных в одном потоке становится видимым для других
потоков.


Изменение данных одним поток становится видим для других, если:
 Пишущий поток освобождает блокировку, которую тут же получает другой
  поток
 Для volatile поля все изменения сделанные в одном потоке сразу же видны
  другим потокам.
 При первом обращении к полю объекта поток увидит либо его значение по
  умолчанию, либо значение записанное каким-либо потоком.




Page  19
Вторая семантика synchronized

//Thread 1
x = 1;
synchronized(this){
    y = 2;
}                                       Все переменные записаны в память


    Все переменные читаются из памяти    //Thread 2
                                         synchronized(this){
                                           a = x;
                                         }
                                         b = y;




Page  20
Модель памяти Java. Видимость данных


 После окончания работы конструктора все final поля становятся видимыми
  другим потокам.
 Все модификации сделанные в конструкторе видны в finalize()
 При запуске нового потока, все модификации текущего потока становятся
  видны
 При завершении потока, все модификации переменных становятся
  видимыми другим потокам




Page  21
Модель памяти Java.

Изменение порядка выполнения инструкций
 Компилятором (может менять инструкции местами для оптимизации, если
  это не нарушает логики выполнения программы*)
 Процессором
 Процессором может быть изменен порядок записи переменных из кэша в
  оперативную память (может производится в порядке отличном от того как
  они изменялись программой)


Основной принцип:
Программа должна сохранять семантику последовательного и
однопоточного выполнения.




Page  22
Модель памяти Java. Работа над ошибками.


До Java 5:
 Не гарантированности видимости final полей класса после завершения
  конструктора.
  – Immutable объекты не были потокобезопасными
            Можно было получить ошибку в подобном коде:
            String s1 = "string";
            String s2 =   s1.substring(2);
            if (s2 != s2) throw new AssertionError();




Page  23
Модель памяти Java. Работа над ошибками.

Чтение и запись volatile переменных были упорядочены между собой, но не
упорядочены относительно других операций.
Следующий код не работал:
            Map configOptions;
            char[] configText;
            volatile boolean initialized = false;
            . . .
            // In thread A
            configOptions = new HashMap();
            configText = readConfigFile(fileName);
            processConfigOptions(configText, configOptions);
            initialized = true;
            . . .
            // In thread B
            while (!initialized)
             sleep();
            // use configOptions



Page  24
Volatile переменные


volatile int value;


Семантически эквивалентно


private int value;
final synchronized void set(int value) {
            this.value = value;
}
final synchronized float get() {
            return value;
}

Page  25
Volatile переменные


Использовать volatile можно, если:
 Доступ к полю происходит из разных потоков, но вне других блоков
  синхронизации (необходимых для других нужд)
 Поле не входит ни в какие инварианты для состояния объекта
 Модификация поля не зависит от его текущего значения
 В поле могут быть записаны только семантически корректные значения


Например, один поток может модифицировать поле, а другие только читать.




Page  26
Volatile массивы


Рассмотрим массив:
volatile int [] arr = new int[SIZE];


arr = arr;
int x = arr[0];
arr[0] = 1;


Сама ссылка на массив – volatile, но элементы массива - нет. Это же
применимо и к коллекциям ArrayList, LinkedList и т.д.


Есть атомарные реализации массивов с volatile элементами:
AtomicIntegerArray, AtomicLongArray и AtomicReferenceArray<T>


Page  27
Безопасная публикация объектов


До завершения конструктора объект может быть не целостным (не все поля
инициализированы, не все инварианты состояния выполняются)


Источник неприятностей
 ссылка на объект доступна другому потоку до создания объекта и нет
  никаких специальных синхронизаций




Page  28
Пример небезобасной инициализации


public Holder holder;
public void initialize() {
            holder = new Holder(42);
}                                                       //Thread1
...                                                     initialize();

public class Holder {                                   //Thread2
            private int n;                              if (holder != null){
                                                                  holder.assertSanity();
                                                        }
            public Holder(int n) {
                     this.n = n;
            }
            public void assertSanity() {
                     if (n != n)
                              throw new AssertionError("This statement is false.");
            }
}

Page  29
Антипаттерн – публикация this в конструкторе


public class ThisEscape {
...
            public ThisEscape(EventSource source) {
                  source.registerListener(new EventListener() {
                         public void onEvent(Event e) {
                               doSomething(e);
                         }
                  });
                  ...
            }
}

Page  30
Решение – использовать фабричный метод


public class SafeListener {
            private final EventListener listener;
            private SafeListener() {
                     listener = new EventListener() {
                              public void onEvent(Event e) {
                                       doSomething(e);
                              }
                     };
            }
            public static SafeListener newInstance(EventSource source) {
                     SafeListener safe = new SafeListener();
                     source.registerListener(safe.listener);
                     return safe;
            }
}


Page  31
Принципы потокобезопасной инициализации


 Инициализировать ссылку на объект в статической инициализации
 Делать объект доступным другим потокам через ссылку, которая:
  – volatile
  – AtomicReference
  – final поле потокобезопасно инициализированного объекта
  – поле, доступ к которому синхронизирован




Page  32
Неизменяемые (immutable) объекты


- Объекты, состояние которых не изменяется в течение жизни объекта
Например: String, Integer, Double и т.д.


Объект эффективно считается неизменяемым, если:
 его состояние не может быть изменено после создания
 все поля определяющие состояние – final*
 объект инициализирован потокобезопасно (ссылка на него недоступна
  другим потокам до завершения конструктора)


Immutable объекты всегда потокобезопасны.



Page  33
Пример immutable класса


public class ImmutablePoint {
            private final double x;
            private final double y;


            public ImmutablePoint(double x, double y) {
                     this.x = x;
                     this.y = y;
            }
}




Page  34
Реализация потокобезопасной инициализации синглтона

Задача: есть синглтон. Надо реализовать его отложенную потокобезопасную инициализацию.


public class Singleton {
            private static Singleton instance;


            public static synchronized Singleton getInstance() {
                     if (instance == null) {
                                instance = new Singleton();
                     }
                     return instance;
            }


            private Singleton(){
                     ...
            }
}



Page  35
Антипаттерн – Блокировка с двойной проверкой (DCL)


public static Singleton getInstance() {
            if (instance == null) {
                    synchronized (Singleton.class) {                 // 1
                               if (instance == null) {               // 2
                                       instance = new Singleton();   // 3
                               }
                    }
            }
            return instance;
}




Page  36
Вариант исправления


public static Singleton getInstance() {
            if (instance == null) {
                     synchronized (Singleton.class) { // 1
                               Singleton inst = instance; // 2
                               if (inst == null) {
                                        synchronized (Singleton.class) { // 3
                                                 inst = new Singleton(); // 4
                                        }
                                        instance = inst; // 5
                               }
                     }
            }
            return instance;
}




Page  37
Потокобезопасное решение начиная с Java 5


Так как поменялась семантика volatile переменных, можно определить
instance так:
private static volatile Singleton instance;
тогда в строке
instance = new Singleton();
не может произойти перестановки операций вызова конструктора и
присвоения значения переменной.


Но все же использовать не рекомендуется.




Page  38
Корректная реализация отложенной инициализации
синглтона

public class Something {
            private static class LazySomethingHolder {
                    public static Something something = new Something();
            }


            private Something(){
                    ...
            }


            public static Something getInstance() {
                    return LazySomethingHolder.something;
            }
            ...
}

Page  39
Базовые элементы аппаратной синхронизации


Помимо синхронизации для потокобезопасного доступа к разделяемыми
переменным можно использовать атомарные инструкция вида сравнение-с
обменом (Compare-and-Swap, CAS):


boolean compareAndSwap(reference, expectedValue, newValue)


Изменение значения переменной происходит, только если текущее значение
совпадает с ожидаемым. В противном случае ничего не происходит


CAS поддерживается на аппаратном уровне всеми современными
процессорами.



Page  40
Сравнение с обменом (CAS)


CAS семантически эквивалентна следующему коду


public class SimulatedCAS {
            private int value;


            public synchronized int getValue() { return value; }


            public synchronized boolean compareAndSwap(int expectedValue, int newValue) {
                     if (value == expectedValue) {
                                 value = newValue;
                                 return true;
                     }
                     return false;
       }
}

Page  41
Атомарные типы данных


Начиная с Java 5 появились реализации
AtomicInteger, AtomicBoolean, AtomicReference и др.
(java.util.concurrent.atomic.*), которые предоставляют атомарные
операции основанные на CAS.
Атомарные типы ведут себя так же, как volatile переменные.


Пример методов класса AtomicInteger:
 int addAndGet(int i, int delta)
 int decrementAndGet()
 int getAndDecrement()
 int getAndIncrement()


Page  42
Реализация потокобезопасного счётчика


public static Counter counter = new Counter();


public class Counter {
      private long value = 0;


      public synchronized long getValue() {
            return value;
      }


      public synchronized long increment() {
            return ++value;
      }
                                                 //Thread1
}
                                                 print(counter.getValue());

                                                 //Thread2
                                                 counter.increment();
Page  43
Реализация счётчика с помощью AtomicLong

public class Counter {
            private AtomicLong value = new AtomicLong();

                                                           private volatile long value;
            public long getValue() {
                     return value.get();                   public final long get() {
                                                                    return value;
            }
                                                           }

            public long increment() {
                     return value.incrementAndGet();
            }
                                  public final long incrementAndGet() {
}                                          for (;;) {
                                                     long current = get();
                                                     long next = current + 1;
                                                     if (compareAndSet(current, next))
                                                              return next;
                                           }
                                  }



Page  44
Неблокирующие алгоритмы


Потокобезопасные алгоритмы, использующие для доступа к общим данным
CAS, называются неблокирующими.


Основной принцип:
некоторый шаг алгоритма выполняется гипотетически, с осознанием того, что
он должен быть выполнен повторно, если операция CAS закончилась
неудачно.


Неблокирующие алгоритмы часто называют оптимистическими, потому что
они выполняются с предположением о том, что не будет конфликтных
ситуаций



Page  45
Потокобезопасный стек. Алгоритм Трайбера

  import java.util.concurrent.atomic.AtomicReference;
  public class ConcurrentStack<E> {
            AtomicReference<Node<E>> head = new AtomicReference<Node<E>>();
            static class Node<E> {
                final E item;
                Node<E> next;
                public Node(E item) { this.item = item; }
            }


            public void push(E item) {
                Node<E> newHead = new Node<E>(item);
                Node<E> oldHead;
                do {
                       oldHead = head.get();
                       newHead.next = oldHead;
                } while (!head.compareAndSet(oldHead, newHead));
            }
Page  46
Потокобезопасный стек. Алгоритм Трайбера.


 public E pop() {
            Node<E> oldHead;
            Node<E> newHead;
            do {
                   oldHead = head.get();
                   if (oldHead == null)
                       return null;
                   newHead = oldHead.next;
            } while (!head.compareAndSet(oldHead, newHead));
            return oldHead.item;
      }
}




Page  47
Неблокирующая очередь. Алгоритм Майкла-Скота

class LinkedQueue<E> implements Queue<E> {
             private static class Node<E> {
                      E item;
                      final AtomicReference<Node<E>> next;


                      Node(E item, Node<E> next) {
                                this.item = item;
                                this.next = new AtomicReference<Node<E>>(next);
                      }
             }


             private AtomicReference<Node<E>> head = new AtomicReference<Node<E>>(
                                                             new Node<E>(null, null));
             private AtomicReference<Node<E>> tail = head;




 Page  48
Неблокирующая очередь. Добавление элемента.

public boolean offer(E item) {
            Node<E> newNode = new Node<E>(item, null);
            for (;;) {
                     Node<E> curTail = tail.get();
                     Node<E> residue = curTail.next.get();
                     if (curTail == tail.get()) {
                              if (residue == null) {
                                         if (curTail.next.compareAndSet(null, newNode)) {
                                                  tail.compareAndSet(curTail, newNode);
                                                  return true;
                                         }
                              } else {
                                         tail.compareAndSet(curTail, residue);
                              }
                     }
            }
}

Page  49
Неблокирующая очередь. Получение первого элемента.

public E poll() {
            for (;;) {
                         Node<E> curHead = head.get();
                         Node<E> curTail = tail.get();
                         Node<E> newHead = curHead.next.get();
                         if (curHead == head.get()) {
                                   if (curHead == curTail) {
                                              if (newHead == null) {
                                                         return null;
                                              } else {
                                                         tail.compareAndSet(curTail, newHead);
                                              }
                                   } else if (head.compareAndSet(curHead, newHead)) {
                                              E item = newHead.item;
                                              if (item != null) {
                                                         newHead.item = null;
                                                         return item;
                                              }
                                   }
                         }
            }
Page  50
}
Неблокирующие коллекции в Java

С Java 5:
  – ConcurrentHashMap<K,V> (Использует CAS + гранулярные блокировки для
    модификации)
  – ConcurrentLinkedQueue<E>
С Java 6:
  – ConcurrentSkipListMap<K,V>
  – ConcurrentSkipListSet<E>
C Java 7:
  – ConcurrentLinkedDeque<E>


Плюс: нет взаимных блокировок и ошибок одновременной модификации
Минусы: ниже производительность при интенсивной модификации.
Операция size() линейная по времени.

Page  51
Копирование при модификации


Другой подход – копировать данные при изменении коллекции.
Реализации:
  – CopyOnWriteArrayList<E>
  – CopyOnWriteArraySet<E>


Плюсы:
  – нет блокировок при чтении
  – iterator() работает со своей копией коллекции на момент вызова метода
  – Операции записи синхронизированы и делают копию массива с данными
Минусы:
  – экстенсивное потребление памяти


Page  52
Список с пропусками




     Поиск, вставка, удаление – O(log n)




Page  53
Fork/Join


Fork/Join - фреймворк для многопоточного программирования в Java 7
основанный на легковесных потоках (задачах).
Есть бэкпорт фреймворка для Java 6.


Основные классы:
 ForkJoinPool – управляет распределением задач по потока, управляет
  запуском, аналог ExecutorServer
 ForkJoinTask/RecursiveTask/RecursiveAction – аналоги
  Thread/Callable/Runnable




Page  54
Fork/Join на примере


interface TreeNode {
     Iterable<TreeNode> getChildren(); //Retrieve values sequentially by net from some service
     long getValue();
}


public class MaxCounter extends RecursiveTask<Long>{


            private final TreeNode root;


            public MaxCounter(TreeNode root) {
                        this.root = root;
            }


            public static long maxValue(TreeNode root){
                return new ForkJoinPool(100).invoke(new MaxCounter(root));
            }




Page  55
Fork/Join на примере

     @Override
     protected Long compute() {
            List<MaxCounter> subTasks = new ArrayList<>();


            for(TreeNode child : root.getChildren()) {
            MaxCounter task = new MaxCounter(child);
                 task.fork();
                 subTasks.add(task);
            }


            long max = 0;
            for(MaxCounter task : subTasks) {
                long result = task.join();
                if (result > max) max = result;
            }


            return max;
     }
}



Page  56
Fork/Join – управление блокировками

class ManagedLocker implements ManagedBlocker {
            final ReentrantLock lock;
            boolean hasLock = false;


            ManagedLocker(ReentrantLock lock) {
                      this.lock = lock;
            }


            public boolean block() {
                      if (!hasLock)
                                 lock.lock();
                      return true;
            }


            public boolean isReleasable() {
                      return hasLock || (hasLock = lock.tryLock());
            }
}
…
ForkJoinPool.managedBlock(new ManagedLocker(lock));

Page  57
Многопоточное программирование в J2EE


EJB контейнер берет на себя управление системными ресурсами:
безопасность, управление потоками, управление ресурсами (pooling,
управление транзакциями), позволяет масштабировать приложение.
Вследствие этого возникают множество ограничений на использование API в
приложениях.


Enterprise bean’ы не должны:
1.     управлять потоками выполнения
2.     использовать средства синхронизации для разграничения доступа к
       ресурсам между экземплярами EJB
3.     работать с файловой системой
4.     использовать reflection, native вызовы
И т.д.
Page  58
                                                                    58
Средства параллельного программирования в J2EE


 WorkManager API (JSR-237)
 Messaging (JMS, MDB)
 Асинхронный вызов EJB (@Asynchronous в EJB 3.1)
 Вызов EJB по расписанию (Timer Service, @Timeout, @Schedule в EJB 3.1)
 Синхронизация методов в EJB (@Lock в EJB 3.1)
 Асинхронный вызов веб сервисов (JAX-WS)
 Асинхронный ответ в сервлете (Servlet 3.0)




Page  59
                                                                     59
WorkManager API



JSR-237 - API для параллельного выполнения задач в среде J2EE.


Реализации:
 В Oracle Weblogic и IBM WebShpere используется реализация JSR-237
  CommonJ
 В JBoss – WorkManager API из JCA (JSR-322)




Page  60
                                                                  60
WorkManager API




Page  61
                  61
Использование WorkManager’а


 Реализовать интерфейс Work. Фактические действия содержатся здесь
 Реализовать интерфейс WorkListener для получения результата выполнения
 Настроить WorkManager в сервере приложений (параметры pool’а
  потоков, сервер или кластер для выполнения и др.)
 Добавить ресурс в ejb-jar.xml или web.xml




Page  62
                                                                 62
Реализация интерфейса Work

    import commonj.work.Work;


    public class WorkImpl implements Work {

            @Override
            public void run() {
                 // Собственно сами действия
            }

            @Override
            public void release() {
                 // WorkManager собирается остановить выполнение
            }

            @Override
            public boolean isDaemon() {
                 // true если задача требует много времени на выполнение
                 return false;
            }

    }




Page  63
                                                                     63
Реализация интерфейса WorkListener

    import commonj.work.WorkEvent;
    import commonj.work.WorkListener;

    public class WorkListenerImpl implements WorkListener {

            @Override
            public void workAccepted(WorkEvent workEvent) {
            }

            @Override
            public void workCompleted(WorkEvent workEvent) {
            }

            @Override
            public void workRejected(WorkEvent workEvent) {
            }

            @Override
            public void workStarted(WorkEvent workEvent) {
            }

    }

Page  64
                                                               64
Пример создания задачи

            //#1. Получить WorkManager из JNDI
            WorkManager workManager;
            InitialContext ctx = new InitialContext();
            this.workManager =
 (WorkManager)ctx.lookup("java:comp/env/wm/TestWorkManager");

            //#2. Создать Work and WorkListener
            Work work = new WorkImpl("HelloWorld");
            WorkListener workListener=new WorkListenerImpl();

            //#3. Назначить выполнение задачи
            WorkItem workItem = workManager.schedule(work,
 workListener);

            List<WorkItem> workItemList=new ArrayList<WorkItem>();
            workItemList.add(workItem);

            //#4. Дождаться выполнения всех задач
            this.workManager.waitForAll(workItemList,
 WorkManager.INDEFINITE);

            //#5. Получить результаты выполнения, если требуется
            WorkImpl workImpl= (WorkImpl)workItem.getResult();


Page  65
                                                                     65
Контекст выполнения задач

  Для POJO задач
   Задача выполняется с тем же контекстом безопасности
   Java:comp вызывающей компоненты доступен в задаче
   Можно использовать UserTransaction
   Можно использовать удаленное выполнение


  Для EJB задач
   Это обязательно должна быть @Local ссылка на @Stateless session bean
   Задача выполняется с тем же контекстом безопасности и он может быть
    переопределен в EJB
   Можно использовать декларативные транзакции
   Используется java:comp enterprise bean’а

Page  66
                                                                    66
Удаленное выполнение задач


JSR-237 WorkManager может выполнять задачи на удалённых JVM:
 Work объект должен реализовывать Serializable
 Эта функциональность зависит от сервера приложений
 Реализовано в CommonJ




Page  67
                                                               67
Java Messaging System


Java Message Service (JMS) — стандарт middleware для
рассылки сообщений, позволяющий приложениям, выполненным на
платформе J2EE, создавать, посылать, получать и читать сообщения.


Может использоваться как транспорт для
 вызова внутренних компонет
 удаленного вызова
 вызова SOAP веб сервисов


Можно использовать как синхронно, так и асинхронно



Page  68
                                                                    68
Java Messaging System



Преимущества JMS:
 Надежность
 Гарантированность доставки (поддержка транзакций)
 Масштабируемость
 Асинхронность




Page  69
                                                      69
Отправка JMS сообщения



        @Resource(mappedName="jms/ConnectionFactory")
        private static ConnectionFactory connectionFactory;

        @Resource(mappedName="jms/Queue")
        private static Queue queue;


        connection = connectionFactory.createConnection();
        session = connection.createSession(true,
        Session.SESSION_TRANSACTED);
        messageProducer = session.createProducer(queue);

        message = session.createTextMessage();

        for (int i = 0; i < NUM_MSGS; i++) {
            message.setText("This is message " + (i + 1));
            System.out.println("Sending message: " +
        message.getText());
            messageProducer.send(message);
        }




Page  71
                                                              71
Получение JMS сообщения

    @MessageDriven(mappedName="jms/Queue", activationConfig = {
            @ActivationConfigProperty(propertyName =
    "destinationType",
                                      propertyValue =
    "javax.jms.Queue")
        })
    public class SimpleMessageBean implements MessageListener {

            public void onMessage(Message inMessage) {
                TextMessage msg = null;

                try {
                    if (inMessage instanceof TextMessage) {
                        msg = (TextMessage) inMessage;
                        logger.info("MESSAGE BEAN: Message received: " +
                            msg.getText());
                    } else {
                        logger.warning("Message of wrong type: " +
                            inMessage.getClass().getName());
                    }
                } catch (JMSException e) {
                    e.printStackTrace();
                    mdc.setRollbackOnly();
                } catch (Throwable te) {
                    te.printStackTrace();
                }
            }
                                       }

Page  72
                                                                           72
Асинхронный вызов EJB


В EJB 3.1 появилась простая возможность делать асинхронные вызовы:
добавить @Asynchronous аннотацию к методу или всему классу.


При вызове такого метода клиент не будет дожидаться окончания
выполнения.




Page  73
                                                                 73
Асинхронный вызов EJB


        Существует два вида асинхронных методов:
        •Метод возвращает void.
        •Метод возвращает Future<?>
       @Stateless
       //@Asynchronous
       public class AsyncBean {
         @Asynchronous
         public void ignoreResult(int a, int b) {
             // …
         }

            @Asynchronous
            public Future<Integer> longProcessing(int a, int b) {
                return new AsyncResult<Integer>(a * b);
            }
       }




Page  74
                                                                    74
EJB Timer Services


EJB контейнер предоставляет возможность запускать методы по рассписанию


 Можно запускать методы по расписанию, через определенное время, через
  определенные интервалы
 Можно создавать программно, аннотациями или в deployment
  конфигурации
 Таймеры можно создавать в @Stateless, @Singleton и @MessageDriven
  bean’ах
 Таймеры persistent по умолчанию




Page  75
                                                                 75
Пример таймера

 @Singleton
 @Startup
 public class DummyTimer3 {
   @Resource TimerService timerService;

   @PostConstruct
   public void initTimer() {
     if (timerService.getTimers() != null) {
       for (Timer timer : timerService.getTimers()) {
         if (timer.getInfo().equals("dummyTimer3.1") ||
             timer.getInfo().equals("dummyTimer3.2"))
           timer.cancel();
       }
     }
     timerService.createCalendarTimer(
       new ScheduleExpression().
           hour("*").minute("*").second("*/10"), new
 TimerConfig("dummyTimer3.1", true));
     timerService.createCalendarTimer(
       new ScheduleExpression().
 hour("*").minute("*").second("*/45"), new TimerConfig("dummyTimer3.2",
 true));
   }
   @Timeout
   public void timeout(Timer timer) {
     System.out.println(getClass().getName() + ": " + new Date());
   }
 }
Page  76
                                                                          76
Пример таймера EJB 3.1

 @Schedules({
       @Schedule(hour="*", minute="*", second="*/10",
 info="every tenth"),
       @Schedule(hour="*", minute="*", second="*/45",
 info="every 45th")
     })
     public void printTime(Timer timer) {
       System.out.println(getClass().getName() + ": " +
           new Date() + ":" +
           timer.getInfo());
     }




Page  77
                                                          77
Синхронизация методов в EJB


Новые возможности в EJB 3.1:
 @Singleton – enterprise bean, который реализован как singleton session bean.
  Существует только один экземпляр bean’а. Можно использовать
  межпоточную синхронизацию.


Для @Singleton bean’ов можно указывать порядок создания:
 @Startup – bean инициализируется при запуске приложения
 @DependsOn(“MyBean1”, “MyBean2”) – указанные bean’ы должны быть
  инициализированы до




Page  78
                                                                      78
Синхронизация управляемая контейнером


            @Singleton
            @AccessTimeout(value=120000)
            public class BufferSingletonBean {
              private StringBuffer buffer;

                @Lock(READ)
                private String getContent(){
                    return buffer.toString();
                }

                @Lock(WRITE)
                public void append(String string) {
                    buffer.append(string);
                }

                @Lock(WRITE)
                @AccessTimeout(value=360000)
                public void flush {
                  //Save to db ...
                  buffer = new StringBuffer();
                }
            }




Page  79
                                                      79
Программная синхронизация
    @ConcurrencyManagement(BEAN)
    @Singleton
    public class BufferSingletonBean {
      private StringBuffer buffer;
      private ReadWriteLock lock = new ReentrantReadWriteLock();

        private String getContent(){
             try{
                  lock.readLock().lock();
                  return buffer.toString();
             }finally{
                  lock.readLock().unlock();
             }
        }
        public void append(String string) {
             try{
                  lock.writeLock().lock();
                  buffer.append(string);
             }finally{
                  lock.writeLock().unlock();
             }
        }
        public void flush {
             try{
                  lock.writeLock().lock();
                  //Save to db ...
                  buffer = new StringBuffer();
             }finally{
                  lock.writeLock().unlock();
             }
        }
    }

Page  80
                                                                   80
Асинхронный вызов веб сервисов


   Начиная с JAX_WS 2.0 асинхронный вызов веб сервиса
   можно просто реализовать на стороне клиента.

   Клиентский прокси будет сам управлять асинхронным
   вызовом.

   Для этого надо:
   1. Добавить пользовательский binding
   2. Сгенерировать асинхронный клиентский код
   3. Вызывать веб сервис через асинхронные методы


Page  81
                                                        81
Генерация клиентского кода для асинхронного вызова


Указать пользовательский binding при вызове wsimport
<bindings node="wsdl:definitions"> <package
name="com.company.jaxws.stockquote.client"/>
        <enableAsyncMapping>true</enableAsyncMapping>
</bindings>




Ant задача:
<wsimport debug="${debug}" verbose="${verbose}" keep="${keep}"
extension="${extension}" destdir="${build.classes.home}" wsdl="${client.wsdl}">
<binding dir="${basedir}/etc" includes="${client.binding.async}" />
</wsimport>
Page  82
                                                                         82
Клиентский код

       @WebService(name = "StockQuote")
       public interface StockQuote {
           …
           public Response<GetQuoteResponse>getQuoteAsync(
               @WebParam(name = "arg0", targetNamespace = "")
               String arg0);
           …
           public Future<?>getQuoteAsync(String arg0,
               AsyncHandler<GetQuoteResponse>asyncHandler);

            …
            public double getQuote(
                String arg0);
       }




Page  83
                                                                83
Вызов веб сервиса

            //#1
            Response<GetQuoteResponse>resp = port.getQuoteAsync (code);
            while( ! resp.isDone()){
                    //some client side processes
            }
            GetQuoteResponse output = resp.get();

            //#2

          port.getQuoteAsync ("MHP", new GetQuoteCallbackHandler (){
               private GetQuoteResponse output;
                 public void handleResponse
(Response<GetQuoteResponse>response) {
                         try {
                       output = response.get ();
                    } catch (ExecutionException e) {
                      e.printStackTrace ();
                    } catch (InterruptedException e) {
                      e.printStackTrace ();
                    }
               }
          );


Page  84
                                                                     84
Асинхронный ответ в сервлете

                        @WebServlet("/foo" asyncSupported=true)
                         public class MyServlet extends HttpServlet {
                              public void doGet(HttpServletRequest req,
            HttpServletResponse res) {
                                  ...
                                  AsyncContext aCtx = request.startAsync(req,
            res);
                                  ScheduledThreadPoolExecutor executor = new
            ThreadPoolExecutor(10);
                                  executor.execute(new AsyncWebService(aCtx));
                              }
                         }

                         public class AsyncWebService implements Runnable {
                              AsyncContext ctx;
                              public AsyncWebService(AsyncContext ctx) {
                                  this.ctx = ctx;
                              }
                              public void run() {
                                  // Какие-либо действия
                                  ctx.dispatch("/render.jsp");
                         }
                     }




Page  85
                                                                                 85
Полезная литература по теме


 Concurrency in Practice, Brian Goetz, Doug Lea, Tim Peierls, Joshua
  Bloch, Joseph Bowbeer, David Holmes
 Pattern-Oriented Software Architecture, Patterns for Concurrent and
  Networked Objects, F. Buschmann, K.Henney, D. Schmidt, M. Stal, H. Rohnert
 Patterns in java, Mark Grand
 Concurrent Programming in Java, Design Principles and Patterns, Doug Lea
 Patterns for Parallel Programming, T.Mattson, B.Sanders, B. Massingill




Page  86
                                                                           86
Интернет ресурсы


 Leveraging EJB Timers for J2EE Concurrency
  http://www.devx.com/Java/Article/33694/1954
 The Work Manager API: Parallel Processing Within a J2EE
  Container
  http://www.devx.com/Java/Article/28815/1954
 Simple Asynchronous methods in EJB 3.1
  http://javahowto.blogspot.com/2010/03/simple-asynchronous-
  methods-in-ejb-31.html
 Java Memory Model
  http://gee.cs.oswego.edu/dl/cpj/jmm.html


Page  87
                                                            87
Интернет ресурсы


 Double-checked locking
  http://www.ibm.com/developerworks/java/library/j-
  dcl/index.html
 Non-blocking algorithms
  http://www.ibm.com/developerworks/java/library/j-jtp04186/
 Fork/Join framework
  http://www.oracle.com/technetwork/articles/java/fork-join-
  422606.html
  http://www.ibm.com/developerworks/java/library/j-
  jtp03048/index.html


Page  88
                                                               88
Ваши вопросы?




Page  89
                            89
Спасибо за внимание!




Page  90
                                   90

Contenu connexe

Tendances

Секреты сборки мусора в Java [DUMP-IT 2012]
Секреты сборки мусора в Java [DUMP-IT 2012]Секреты сборки мусора в Java [DUMP-IT 2012]
Секреты сборки мусора в Java [DUMP-IT 2012]aragozin
 
Другая виртуализация
Другая виртуализацияДругая виртуализация
Другая виртуализацияYandex
 
Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4HighLoad2009
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Ontico
 
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)Ontico
 
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...WebCamp
 
Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Alexander Syrotenko
 
WebCamp 2016: Python.Максим Климишин.Типизированный Python
WebCamp 2016: Python.Максим Климишин.Типизированный PythonWebCamp 2016: Python.Максим Климишин.Типизированный Python
WebCamp 2016: Python.Максим Климишин.Типизированный PythonWebCamp
 
Cборка мусора в Java без пауз (HighLoad++ 2013)
Cборка мусора в Java без пауз  (HighLoad++ 2013)Cборка мусора в Java без пауз  (HighLoad++ 2013)
Cборка мусора в Java без пауз (HighLoad++ 2013)aragozin
 
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли..."Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...Ontico
 
Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Ontico
 
Caching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaCaching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaAndrei Pangin
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOSquakke
 
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)Ontico
 
PostgreSQL Vacuum: Nine Circles of Hell
PostgreSQL Vacuum: Nine Circles of HellPostgreSQL Vacuum: Nine Circles of Hell
PostgreSQL Vacuum: Nine Circles of HellAlexey Lesovsky
 
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей РагозинDUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозинit-people
 
Применение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияПрименение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияcorehard_by
 
Scala performance под капотом
Scala performance под капотомScala performance под капотом
Scala performance под капотомRoman Grebennikov
 
Управление памятью в CPython
Управление памятью в CPythonУправление памятью в CPython
Управление памятью в CPythonAnton Patrushev
 

Tendances (20)

Секреты сборки мусора в Java [DUMP-IT 2012]
Секреты сборки мусора в Java [DUMP-IT 2012]Секреты сборки мусора в Java [DUMP-IT 2012]
Секреты сборки мусора в Java [DUMP-IT 2012]
 
Другая виртуализация
Другая виртуализацияДругая виртуализация
Другая виртуализация
 
Dz Java Hi Load 0.4
Dz Java Hi Load 0.4Dz Java Hi Load 0.4
Dz Java Hi Load 0.4
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
libfpta — обгоняя SQLite и Tarantool / Леонид Юрьев (Positive Technologies)
 
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...
WebCamp2016:Front-End.Максим Климишин.Теоретические и практические концепции ...
 
Presentation_1369080393540
Presentation_1369080393540Presentation_1369080393540
Presentation_1369080393540
 
Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?Multithreading in JS. Myth or reality?
Multithreading in JS. Myth or reality?
 
WebCamp 2016: Python.Максим Климишин.Типизированный Python
WebCamp 2016: Python.Максим Климишин.Типизированный PythonWebCamp 2016: Python.Максим Климишин.Типизированный Python
WebCamp 2016: Python.Максим Климишин.Типизированный Python
 
Cборка мусора в Java без пауз (HighLoad++ 2013)
Cборка мусора в Java без пауз  (HighLoad++ 2013)Cборка мусора в Java без пауз  (HighLoad++ 2013)
Cборка мусора в Java без пауз (HighLoad++ 2013)
 
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли..."Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
"Распределенные" вычисления на мобильных платформах. Зачем еще нужен "металли...
 
Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)Константин Осипов (Mail.Ru)
Константин Осипов (Mail.Ru)
 
Caching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in JavaCaching data outside Java Heap and using Shared Memory in Java
Caching data outside Java Heap and using Shared Memory in Java
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOS
 
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
 
PostgreSQL Vacuum: Nine Circles of Hell
PostgreSQL Vacuum: Nine Circles of HellPostgreSQL Vacuum: Nine Circles of Hell
PostgreSQL Vacuum: Nine Circles of Hell
 
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей РагозинDUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин
DUMP-2012 - Только хардкор! - "Секреты сборки мусора в Java" Алексей Рагозин
 
Применение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюденияПрименение фреймворка GStreamer в системе видеонаблюдения
Применение фреймворка GStreamer в системе видеонаблюдения
 
Scala performance под капотом
Scala performance под капотомScala performance под капотом
Scala performance под капотом
 
Управление памятью в CPython
Управление памятью в CPythonУправление памятью в CPython
Управление памятью в CPython
 

En vedette

Java худеет. Спроси меня как.
Java худеет. Спроси меня как.Java худеет. Спроси меня как.
Java худеет. Спроси меня как.Nikita Lipsky
 
Java Core. Lecture# 1. Intro
Java Core. Lecture# 1. IntroJava Core. Lecture# 1. Intro
Java Core. Lecture# 1. IntroAnton Moiseenko
 
Особенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийОсобенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийUladzimir Kryvenka
 
WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)Igor Khotin
 
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на JavaКлиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на JavaNikita Lipsky
 
Java Ahead-Of-Time compilation
Java Ahead-Of-Time compilationJava Ahead-Of-Time compilation
Java Ahead-Of-Time compilationNikita Lipsky
 
Keynote on JavaDay Omsk 2014 about new features in Java 8
Keynote on JavaDay Omsk 2014 about new features in Java 8Keynote on JavaDay Omsk 2014 about new features in Java 8
Keynote on JavaDay Omsk 2014 about new features in Java 8Alexey Zinoviev
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actualYevgen Levik
 
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...Nikita Lipsky
 
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 днейГотовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 днейSkillFactory
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Javametaform
 
Date & Time in Java SE 8
Date & Time in Java SE 8Date & Time in Java SE 8
Date & Time in Java SE 8Ilya Lapitan
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVMMario Fusco
 
Akka: как я перестал бояться и полюбил асинхронный код
Akka: как я перестал бояться и полюбил асинхронный кодAkka: как я перестал бояться и полюбил асинхронный код
Akka: как я перестал бояться и полюбил асинхронный кодRoman Grebennikov
 
MOM - Message Oriented Middleware
MOM - Message Oriented MiddlewareMOM - Message Oriented Middleware
MOM - Message Oriented MiddlewarePeter R. Egli
 

En vedette (16)

Java худеет. Спроси меня как.
Java худеет. Спроси меня как.Java худеет. Спроси меня как.
Java худеет. Спроси меня как.
 
Java Core. Lecture# 1. Intro
Java Core. Lecture# 1. IntroJava Core. Lecture# 1. Intro
Java Core. Lecture# 1. Intro
 
Java: вчера, сегодня, завтра
Java: вчера, сегодня, завтраJava: вчера, сегодня, завтра
Java: вчера, сегодня, завтра
 
Особенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийОсобенности тестирования NoSql приложений
Особенности тестирования NoSql приложений
 
WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)
 
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на JavaКлиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на Java
 
Java Ahead-Of-Time compilation
Java Ahead-Of-Time compilationJava Ahead-Of-Time compilation
Java Ahead-Of-Time compilation
 
Keynote on JavaDay Omsk 2014 about new features in Java 8
Keynote on JavaDay Omsk 2014 about new features in Java 8Keynote on JavaDay Omsk 2014 about new features in Java 8
Keynote on JavaDay Omsk 2014 about new features in Java 8
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
 
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 днейГотовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
 
Классы и объекты в Java
Классы и объекты в JavaКлассы и объекты в Java
Классы и объекты в Java
 
Date & Time in Java SE 8
Date & Time in Java SE 8Date & Time in Java SE 8
Date & Time in Java SE 8
 
Comparing different concurrency models on the JVM
Comparing different concurrency models on the JVMComparing different concurrency models on the JVM
Comparing different concurrency models on the JVM
 
Akka: как я перестал бояться и полюбил асинхронный код
Akka: как я перестал бояться и полюбил асинхронный кодAkka: как я перестал бояться и полюбил асинхронный код
Akka: как я перестал бояться и полюбил асинхронный код
 
MOM - Message Oriented Middleware
MOM - Message Oriented MiddlewareMOM - Message Oriented Middleware
MOM - Message Oriented Middleware
 

Similaire à Expert Java Day: Java concurrency

8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threadsMERA_school
 
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev FedorProgramming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev FedorFedor Lavrentyev
 
Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Alexey Fyodorov
 
Async Javascript
Async JavascriptAsync Javascript
Async JavascriptGetDev.NET
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerAnton Arhipov
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1Eduard Antsupov
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with JavaAndrei Pangin
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage CollectorOlexandra Dmytrenko
 
Java tricks for high-load server programming
Java tricks for high-load server programmingJava tricks for high-load server programming
Java tricks for high-load server programmingAndrei Pangin
 
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Stfalcon Meetups
 
Java весна 2013 лекция 9
Java весна 2013 лекция 9Java весна 2013 лекция 9
Java весна 2013 лекция 9Technopark
 
Инструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщикаИнструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщикаSQALab
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Android: Как написать приложение, которое не тормозит
Android: Как  написать приложение, которое не тормозитAndroid: Как  написать приложение, которое не тормозит
Android: Как написать приложение, которое не тормозитElena Kotina
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Yandex
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5Technopark
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Yandex
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6Technopark
 

Similaire à Expert Java Day: Java concurrency (20)

8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev FedorProgramming Java - Lection 06 - Multithreading - Lavrentyev Fedor
Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor
 
Unsafe: to be or to be removed?
Unsafe: to be or to be removed?Unsafe: to be or to be removed?
Unsafe: to be or to be removed?
 
Async Javascript
Async JavascriptAsync Javascript
Async Javascript
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
 
Lift, play, akka, rails part1
Lift, play, akka, rails part1Lift, play, akka, rails part1
Lift, play, akka, rails part1
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with Java
 
Память в Java. Garbage Collector
Память в Java. Garbage CollectorПамять в Java. Garbage Collector
Память в Java. Garbage Collector
 
Java tricks for high-load server programming
Java tricks for high-load server programmingJava tricks for high-load server programming
Java tricks for high-load server programming
 
Bytecode
BytecodeBytecode
Bytecode
 
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
 
Java весна 2013 лекция 9
Java весна 2013 лекция 9Java весна 2013 лекция 9
Java весна 2013 лекция 9
 
Java 9 - кратко о новом
Java 9 -  кратко о новомJava 9 -  кратко о новом
Java 9 - кратко о новом
 
Инструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщикаИнструментация среды исполнения в арсенале тестировщика
Инструментация среды исполнения в арсенале тестировщика
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Android: Как написать приложение, которое не тормозит
Android: Как  написать приложение, которое не тормозитAndroid: Как  написать приложение, которое не тормозит
Android: Как написать приложение, которое не тормозит
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5
 
Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"Михаил Давыдов "Масштабируемые JavaScript-приложения"
Михаил Давыдов "Масштабируемые JavaScript-приложения"
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 

Expert Java Day: Java concurrency

  • 2. Виды параллельных вычислений Распараллеливание вычислений может быть на уровне:  систем (распределенные системы, облачные вычисления, grid, cluster, etc.)  процессов (процессы ОС)  потоков Взаимодействие потоков выполнения может быть через:  общую память  общее хранилище данных (базу данных) Page  2
  • 3. Мотивация  Увеличение производительности за счет равномерного использования нескольких процессоров или разнородных систем: – Обработка больших объемов данных (Построение отчетов, бизнес аналитика, индексирование больших хранилищ) – Долгие вычисления (Шифрование, переборные алгоритмы (расчет маршрутов, минимизация издержек, решение математических задач, игры и т.д.)  Масштабируемость системы (если эффективно распараллеливается – можно задействовать больше машин) Page  3 3
  • 4. Мотивация Может исходить из функциональных требований к системе, например:  Система должна быть многопользовательской  Многозадачность  Выполнение каких-либо действий в фоновом режиме или асинхронно  Выполнение каких-либо действий по расписанию  Отзывчивый пользовательский интерфейс Page  4 4
  • 5. Подходы к распараллеливанию вычислений  Разделяемый доступ к общей памяти – блокировки, синхронизация критических секций, барьеры памяти, атомарные инструкции типа CAS, базы данных, транзакции  Обмен сообщениями – Erlang (модель акторов), Occam (CSP) – потоки не имеют доступа к общей памяти, но могут обмениться сообщениями синхронно или асинхронно – Можно реализовать и в Java с использованием Immutable типов, глубокого копирования данных и обмена сообщениями (например JMS)  Полная изолированность потоков вычислений (Одни потоки могут порождать другие при этом передавая на вход данные. Поток обрабатывает исходные данные и возвращает результат породившему потоку) – MapReduce (AppEngine Mapper API, Apache Hadoop), – J2EE WorkManager Page  5
  • 6. Возникающие проблемы  Разделяемый доступ к общей памяти – Сохранение целостности данных при одновременном доступе (thread-safety), • непредсказуемость фактического порядка исполнения инструкций (race conditions) – Конечность вычислений • взаимная блокировка потоков (deadlock) • зависание потока (starvation) • тупиковая ситуация (livelock) • инверсия приоритетов (priority inversion) – Низкая производительность • ожидание очереди на блокировку • переключение контекста (context switching) Page  6
  • 7. Плюсы и минусы подходов  Обмен сообщениями – код всегда потокобезопасен – легче масштабировать – дополнительные затраты на коммуникации – сложнее строить алгоритмы  Изолированные потоки – сложность алгоритмического распараллеливания обработки данных – легко масштабируется – нет всех вышеперечисленных проблем Page  7
  • 10. Взаимная блокировка. final Object lockA = new Object(); final Object lockB = new Object(); new Thread() { public void run() { synchronized (lockA) { synchronized (lockB) { // Do something } } } }.start(); new Thread() { public void run() { synchronized (lockB) { synchronized (lockA) { // Do something } } } }.start(); Page  10
  • 11. Дамп потоков Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.1-b02 mixed mode): "Thread-1" prio=6 tid=0x0000000006998800 nid=0x1a48 waiting for monitor entry [0x00000000076af000] java.lang.Thread.State: BLOCKED (on object monitor) at DeadlockDemo$2.run(DeadlockDemo.java:27) - waiting to lock <0x00000007d5d0a6e8> (a java.lang.Object) - locked <0x00000007d5d0a6f8> (a java.lang.Object) "Thread-0" prio=6 tid=0x0000000006998000 nid=0x1620 waiting for monitor entry [0x000000000748f000] java.lang.Thread.State: BLOCKED (on object monitor) at DeadlockDemo$1.run(DeadlockDemo.java:16) - waiting to lock <0x00000007d5d0a6f8> (a java.lang.Object) - locked <0x00000007d5d0a6e8> (a java.lang.Object) … Page  11
  • 12. Вывод информации о блокировках Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x000000000058ca80 (object 0x00000007d5d0a6e8, a java.lang.Object), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x000000000058f330 (object 0x00000007d5d0a6f8, a java.lang.Object), which is held by "Thread-1" Java stack information for the threads listed above: =================================================== "Thread-1": at DeadlockDemo$2.run(DeadlockDemo.java:27) - waiting to lock <0x00000007d5d0a6e8> (a java.lang.Object) - locked <0x00000007d5d0a6f8> (a java.lang.Object) "Thread-0": at DeadlockDemo$1.run(DeadlockDemo.java:16) - waiting to lock <0x00000007d5d0a6f8> (a java.lang.Object) - locked <0x00000007d5d0a6e8> (a java.lang.Object) Found 1 deadlock. Page  12
  • 13. Взаимная блокировка взаимодействующих объектов class A { public synchronized void callB(B b){ b.process(); } public synchronized void process(){} } class B { public synchronized void callA(A a){ a.process(); } public synchronized void process(){} } final A a = new A(); final B b = new B(); //Thread1 a.callB(b); //Thread 2 b.callA(a); Page  13
  • 14. Дамп потоков "Thread-1" prio=6 tid=0x0000000006ab1000 nid=0x18a8 waiting for monitor entry [0x00000000076ef000] java.lang.Thread.State: BLOCKED (on object monitor) at DeadlockDemo1$A.process(DeadlockDemo1.java:16) - waiting to lock <0x00000007d5d0bac0> (a DeadlockDemo1$A) at DeadlockDemo1$B.callA(DeadlockDemo1.java:26) - locked <0x00000007d5d0cc30> (a DeadlockDemo1$B) at DeadlockDemo1$2.run(DeadlockDemo1.java:45) "Thread-0" prio=6 tid=0x0000000006ab0000 nid=0x17e0 waiting for monitor entry [0x00000000075ef000] java.lang.Thread.State: BLOCKED (on object monitor) at DeadlockDemo1$B.process(DeadlockDemo1.java:31) - waiting to lock <0x00000007d5d0cc30> (a DeadlockDemo1$B) at DeadlockDemo1$A.callB(DeadlockDemo1.java:11) - locked <0x00000007d5d0bac0> (a DeadlockDemo1$A) at DeadlockDemo1$1.run(DeadlockDemo1.java:39) Page  14
  • 15. Случай c аппаратом лучевой терапии Therac-25 Этот аппарат работал в трёх режимах:  Электронная терапия: электронная пушка напрямую облучает пациента; компьютер задаёт энергию электронов от 5 до 25 МэВ.  Рентгеновская терапия: электронная пушка облучает вольфрамовую мишень, и пациент облучается рентгеновскими лучами, проходящими через конусообразный рассеиватель. В этом режиме энергия электронов одна: 25 МэВ.  В третьем режиме никакого излучения не было. На пути электронов (на случай аварии) располагается стальной отражатель, а излучение имитируется светом. Этот режим применяется для того, чтобы точно навести пучок на больное место. Page  15
  • 16. Модель памяти Java. Зачем это нужно знать? public class NoVisibility { private static boolean ready; private static int number; private static class ReaderThread extends Thread { public void run() { while (!ready) Thread.yield(); System.out.println(number); } } public static void main(String[] args) { new ReaderThread().start(); number = 42; ready = true; } } Page  16
  • 17. Модель памяти Java Что это? Это часть спецификации языка Java (JLS chapter 17), описывающая на низком уровне принципы хранения переменных в памяти (полей объекта, класса, элементов массива и т.д.) и доступа потоков к общей памяти. Описывает поведение многопоточных программ в терминах:  Атомарности операций  Видимости данных  Порядка выполнения инструкций Page  17
  • 18. Модель памяти Java. Атомарность операций Какие операции являются атомарными? Атомарные операции – эффект которых на систему семантически такой же как если бы они выполнялись мгновенно и результат не зависел от работы других потоков. Согласно модели памяти Java: – Чтение и запись значений в память соответствующую переменной (кроме типов long и double) является атомарной операцией – Чтение и запись указателей атомарно вне зависимости от разрядности указателя (32 или 64 бита) – Чтение и запись volatile long или double переменных атомарно Page  18
  • 19. Модель памяти Java. Видимость данных Видимость данных - это правила, описывающие при каких обстоятельствах изменение переменных в одном потоке становится видимым для других потоков. Изменение данных одним поток становится видим для других, если:  Пишущий поток освобождает блокировку, которую тут же получает другой поток  Для volatile поля все изменения сделанные в одном потоке сразу же видны другим потокам.  При первом обращении к полю объекта поток увидит либо его значение по умолчанию, либо значение записанное каким-либо потоком. Page  19
  • 20. Вторая семантика synchronized //Thread 1 x = 1; synchronized(this){ y = 2; } Все переменные записаны в память Все переменные читаются из памяти //Thread 2 synchronized(this){ a = x; } b = y; Page  20
  • 21. Модель памяти Java. Видимость данных  После окончания работы конструктора все final поля становятся видимыми другим потокам.  Все модификации сделанные в конструкторе видны в finalize()  При запуске нового потока, все модификации текущего потока становятся видны  При завершении потока, все модификации переменных становятся видимыми другим потокам Page  21
  • 22. Модель памяти Java. Изменение порядка выполнения инструкций  Компилятором (может менять инструкции местами для оптимизации, если это не нарушает логики выполнения программы*)  Процессором  Процессором может быть изменен порядок записи переменных из кэша в оперативную память (может производится в порядке отличном от того как они изменялись программой) Основной принцип: Программа должна сохранять семантику последовательного и однопоточного выполнения. Page  22
  • 23. Модель памяти Java. Работа над ошибками. До Java 5:  Не гарантированности видимости final полей класса после завершения конструктора. – Immutable объекты не были потокобезопасными Можно было получить ошибку в подобном коде: String s1 = "string"; String s2 = s1.substring(2); if (s2 != s2) throw new AssertionError(); Page  23
  • 24. Модель памяти Java. Работа над ошибками. Чтение и запись volatile переменных были упорядочены между собой, но не упорядочены относительно других операций. Следующий код не работал: Map configOptions; char[] configText; volatile boolean initialized = false; . . . // In thread A configOptions = new HashMap(); configText = readConfigFile(fileName); processConfigOptions(configText, configOptions); initialized = true; . . . // In thread B while (!initialized) sleep(); // use configOptions Page  24
  • 25. Volatile переменные volatile int value; Семантически эквивалентно private int value; final synchronized void set(int value) { this.value = value; } final synchronized float get() { return value; } Page  25
  • 26. Volatile переменные Использовать volatile можно, если:  Доступ к полю происходит из разных потоков, но вне других блоков синхронизации (необходимых для других нужд)  Поле не входит ни в какие инварианты для состояния объекта  Модификация поля не зависит от его текущего значения  В поле могут быть записаны только семантически корректные значения Например, один поток может модифицировать поле, а другие только читать. Page  26
  • 27. Volatile массивы Рассмотрим массив: volatile int [] arr = new int[SIZE]; arr = arr; int x = arr[0]; arr[0] = 1; Сама ссылка на массив – volatile, но элементы массива - нет. Это же применимо и к коллекциям ArrayList, LinkedList и т.д. Есть атомарные реализации массивов с volatile элементами: AtomicIntegerArray, AtomicLongArray и AtomicReferenceArray<T> Page  27
  • 28. Безопасная публикация объектов До завершения конструктора объект может быть не целостным (не все поля инициализированы, не все инварианты состояния выполняются) Источник неприятностей  ссылка на объект доступна другому потоку до создания объекта и нет никаких специальных синхронизаций Page  28
  • 29. Пример небезобасной инициализации public Holder holder; public void initialize() { holder = new Holder(42); } //Thread1 ... initialize(); public class Holder { //Thread2 private int n; if (holder != null){ holder.assertSanity(); } public Holder(int n) { this.n = n; } public void assertSanity() { if (n != n) throw new AssertionError("This statement is false."); } } Page  29
  • 30. Антипаттерн – публикация this в конструкторе public class ThisEscape { ... public ThisEscape(EventSource source) { source.registerListener(new EventListener() { public void onEvent(Event e) { doSomething(e); } }); ... } } Page  30
  • 31. Решение – использовать фабричный метод public class SafeListener { private final EventListener listener; private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } }; } public static SafeListener newInstance(EventSource source) { SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } } Page  31
  • 32. Принципы потокобезопасной инициализации  Инициализировать ссылку на объект в статической инициализации  Делать объект доступным другим потокам через ссылку, которая: – volatile – AtomicReference – final поле потокобезопасно инициализированного объекта – поле, доступ к которому синхронизирован Page  32
  • 33. Неизменяемые (immutable) объекты - Объекты, состояние которых не изменяется в течение жизни объекта Например: String, Integer, Double и т.д. Объект эффективно считается неизменяемым, если:  его состояние не может быть изменено после создания  все поля определяющие состояние – final*  объект инициализирован потокобезопасно (ссылка на него недоступна другим потокам до завершения конструктора) Immutable объекты всегда потокобезопасны. Page  33
  • 34. Пример immutable класса public class ImmutablePoint { private final double x; private final double y; public ImmutablePoint(double x, double y) { this.x = x; this.y = y; } } Page  34
  • 35. Реализация потокобезопасной инициализации синглтона Задача: есть синглтон. Надо реализовать его отложенную потокобезопасную инициализацию. public class Singleton { private static Singleton instance; public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } private Singleton(){ ... } } Page  35
  • 36. Антипаттерн – Блокировка с двойной проверкой (DCL) public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { // 1 if (instance == null) { // 2 instance = new Singleton(); // 3 } } } return instance; } Page  36
  • 37. Вариант исправления public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { // 1 Singleton inst = instance; // 2 if (inst == null) { synchronized (Singleton.class) { // 3 inst = new Singleton(); // 4 } instance = inst; // 5 } } } return instance; } Page  37
  • 38. Потокобезопасное решение начиная с Java 5 Так как поменялась семантика volatile переменных, можно определить instance так: private static volatile Singleton instance; тогда в строке instance = new Singleton(); не может произойти перестановки операций вызова конструктора и присвоения значения переменной. Но все же использовать не рекомендуется. Page  38
  • 39. Корректная реализация отложенной инициализации синглтона public class Something { private static class LazySomethingHolder { public static Something something = new Something(); } private Something(){ ... } public static Something getInstance() { return LazySomethingHolder.something; } ... } Page  39
  • 40. Базовые элементы аппаратной синхронизации Помимо синхронизации для потокобезопасного доступа к разделяемыми переменным можно использовать атомарные инструкция вида сравнение-с обменом (Compare-and-Swap, CAS): boolean compareAndSwap(reference, expectedValue, newValue) Изменение значения переменной происходит, только если текущее значение совпадает с ожидаемым. В противном случае ничего не происходит CAS поддерживается на аппаратном уровне всеми современными процессорами. Page  40
  • 41. Сравнение с обменом (CAS) CAS семантически эквивалентна следующему коду public class SimulatedCAS { private int value; public synchronized int getValue() { return value; } public synchronized boolean compareAndSwap(int expectedValue, int newValue) { if (value == expectedValue) { value = newValue; return true; } return false; } } Page  41
  • 42. Атомарные типы данных Начиная с Java 5 появились реализации AtomicInteger, AtomicBoolean, AtomicReference и др. (java.util.concurrent.atomic.*), которые предоставляют атомарные операции основанные на CAS. Атомарные типы ведут себя так же, как volatile переменные. Пример методов класса AtomicInteger:  int addAndGet(int i, int delta)  int decrementAndGet()  int getAndDecrement()  int getAndIncrement() Page  42
  • 43. Реализация потокобезопасного счётчика public static Counter counter = new Counter(); public class Counter { private long value = 0; public synchronized long getValue() { return value; } public synchronized long increment() { return ++value; } //Thread1 } print(counter.getValue()); //Thread2 counter.increment(); Page  43
  • 44. Реализация счётчика с помощью AtomicLong public class Counter { private AtomicLong value = new AtomicLong(); private volatile long value; public long getValue() { return value.get(); public final long get() { return value; } } public long increment() { return value.incrementAndGet(); } public final long incrementAndGet() { } for (;;) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return next; } } Page  44
  • 45. Неблокирующие алгоритмы Потокобезопасные алгоритмы, использующие для доступа к общим данным CAS, называются неблокирующими. Основной принцип: некоторый шаг алгоритма выполняется гипотетически, с осознанием того, что он должен быть выполнен повторно, если операция CAS закончилась неудачно. Неблокирующие алгоритмы часто называют оптимистическими, потому что они выполняются с предположением о том, что не будет конфликтных ситуаций Page  45
  • 46. Потокобезопасный стек. Алгоритм Трайбера import java.util.concurrent.atomic.AtomicReference; public class ConcurrentStack<E> { AtomicReference<Node<E>> head = new AtomicReference<Node<E>>(); static class Node<E> { final E item; Node<E> next; public Node(E item) { this.item = item; } } public void push(E item) { Node<E> newHead = new Node<E>(item); Node<E> oldHead; do { oldHead = head.get(); newHead.next = oldHead; } while (!head.compareAndSet(oldHead, newHead)); } Page  46
  • 47. Потокобезопасный стек. Алгоритм Трайбера. public E pop() { Node<E> oldHead; Node<E> newHead; do { oldHead = head.get(); if (oldHead == null) return null; newHead = oldHead.next; } while (!head.compareAndSet(oldHead, newHead)); return oldHead.item; } } Page  47
  • 48. Неблокирующая очередь. Алгоритм Майкла-Скота class LinkedQueue<E> implements Queue<E> { private static class Node<E> { E item; final AtomicReference<Node<E>> next; Node(E item, Node<E> next) { this.item = item; this.next = new AtomicReference<Node<E>>(next); } } private AtomicReference<Node<E>> head = new AtomicReference<Node<E>>( new Node<E>(null, null)); private AtomicReference<Node<E>> tail = head; Page  48
  • 49. Неблокирующая очередь. Добавление элемента. public boolean offer(E item) { Node<E> newNode = new Node<E>(item, null); for (;;) { Node<E> curTail = tail.get(); Node<E> residue = curTail.next.get(); if (curTail == tail.get()) { if (residue == null) { if (curTail.next.compareAndSet(null, newNode)) { tail.compareAndSet(curTail, newNode); return true; } } else { tail.compareAndSet(curTail, residue); } } } } Page  49
  • 50. Неблокирующая очередь. Получение первого элемента. public E poll() { for (;;) { Node<E> curHead = head.get(); Node<E> curTail = tail.get(); Node<E> newHead = curHead.next.get(); if (curHead == head.get()) { if (curHead == curTail) { if (newHead == null) { return null; } else { tail.compareAndSet(curTail, newHead); } } else if (head.compareAndSet(curHead, newHead)) { E item = newHead.item; if (item != null) { newHead.item = null; return item; } } } } Page  50 }
  • 51. Неблокирующие коллекции в Java С Java 5: – ConcurrentHashMap<K,V> (Использует CAS + гранулярные блокировки для модификации) – ConcurrentLinkedQueue<E> С Java 6: – ConcurrentSkipListMap<K,V> – ConcurrentSkipListSet<E> C Java 7: – ConcurrentLinkedDeque<E> Плюс: нет взаимных блокировок и ошибок одновременной модификации Минусы: ниже производительность при интенсивной модификации. Операция size() линейная по времени. Page  51
  • 52. Копирование при модификации Другой подход – копировать данные при изменении коллекции. Реализации: – CopyOnWriteArrayList<E> – CopyOnWriteArraySet<E> Плюсы: – нет блокировок при чтении – iterator() работает со своей копией коллекции на момент вызова метода – Операции записи синхронизированы и делают копию массива с данными Минусы: – экстенсивное потребление памяти Page  52
  • 53. Список с пропусками Поиск, вставка, удаление – O(log n) Page  53
  • 54. Fork/Join Fork/Join - фреймворк для многопоточного программирования в Java 7 основанный на легковесных потоках (задачах). Есть бэкпорт фреймворка для Java 6. Основные классы:  ForkJoinPool – управляет распределением задач по потока, управляет запуском, аналог ExecutorServer  ForkJoinTask/RecursiveTask/RecursiveAction – аналоги Thread/Callable/Runnable Page  54
  • 55. Fork/Join на примере interface TreeNode { Iterable<TreeNode> getChildren(); //Retrieve values sequentially by net from some service long getValue(); } public class MaxCounter extends RecursiveTask<Long>{ private final TreeNode root; public MaxCounter(TreeNode root) { this.root = root; } public static long maxValue(TreeNode root){ return new ForkJoinPool(100).invoke(new MaxCounter(root)); } Page  55
  • 56. Fork/Join на примере @Override protected Long compute() { List<MaxCounter> subTasks = new ArrayList<>(); for(TreeNode child : root.getChildren()) { MaxCounter task = new MaxCounter(child); task.fork(); subTasks.add(task); } long max = 0; for(MaxCounter task : subTasks) { long result = task.join(); if (result > max) max = result; } return max; } } Page  56
  • 57. Fork/Join – управление блокировками class ManagedLocker implements ManagedBlocker { final ReentrantLock lock; boolean hasLock = false; ManagedLocker(ReentrantLock lock) { this.lock = lock; } public boolean block() { if (!hasLock) lock.lock(); return true; } public boolean isReleasable() { return hasLock || (hasLock = lock.tryLock()); } } … ForkJoinPool.managedBlock(new ManagedLocker(lock)); Page  57
  • 58. Многопоточное программирование в J2EE EJB контейнер берет на себя управление системными ресурсами: безопасность, управление потоками, управление ресурсами (pooling, управление транзакциями), позволяет масштабировать приложение. Вследствие этого возникают множество ограничений на использование API в приложениях. Enterprise bean’ы не должны: 1. управлять потоками выполнения 2. использовать средства синхронизации для разграничения доступа к ресурсам между экземплярами EJB 3. работать с файловой системой 4. использовать reflection, native вызовы И т.д. Page  58 58
  • 59. Средства параллельного программирования в J2EE  WorkManager API (JSR-237)  Messaging (JMS, MDB)  Асинхронный вызов EJB (@Asynchronous в EJB 3.1)  Вызов EJB по расписанию (Timer Service, @Timeout, @Schedule в EJB 3.1)  Синхронизация методов в EJB (@Lock в EJB 3.1)  Асинхронный вызов веб сервисов (JAX-WS)  Асинхронный ответ в сервлете (Servlet 3.0) Page  59 59
  • 60. WorkManager API JSR-237 - API для параллельного выполнения задач в среде J2EE. Реализации:  В Oracle Weblogic и IBM WebShpere используется реализация JSR-237 CommonJ  В JBoss – WorkManager API из JCA (JSR-322) Page  60 60
  • 62. Использование WorkManager’а  Реализовать интерфейс Work. Фактические действия содержатся здесь  Реализовать интерфейс WorkListener для получения результата выполнения  Настроить WorkManager в сервере приложений (параметры pool’а потоков, сервер или кластер для выполнения и др.)  Добавить ресурс в ejb-jar.xml или web.xml Page  62 62
  • 63. Реализация интерфейса Work import commonj.work.Work; public class WorkImpl implements Work { @Override public void run() { // Собственно сами действия } @Override public void release() { // WorkManager собирается остановить выполнение } @Override public boolean isDaemon() { // true если задача требует много времени на выполнение return false; } } Page  63 63
  • 64. Реализация интерфейса WorkListener import commonj.work.WorkEvent; import commonj.work.WorkListener; public class WorkListenerImpl implements WorkListener { @Override public void workAccepted(WorkEvent workEvent) { } @Override public void workCompleted(WorkEvent workEvent) { } @Override public void workRejected(WorkEvent workEvent) { } @Override public void workStarted(WorkEvent workEvent) { } } Page  64 64
  • 65. Пример создания задачи //#1. Получить WorkManager из JNDI WorkManager workManager; InitialContext ctx = new InitialContext(); this.workManager = (WorkManager)ctx.lookup("java:comp/env/wm/TestWorkManager"); //#2. Создать Work and WorkListener Work work = new WorkImpl("HelloWorld"); WorkListener workListener=new WorkListenerImpl(); //#3. Назначить выполнение задачи WorkItem workItem = workManager.schedule(work, workListener); List<WorkItem> workItemList=new ArrayList<WorkItem>(); workItemList.add(workItem); //#4. Дождаться выполнения всех задач this.workManager.waitForAll(workItemList, WorkManager.INDEFINITE); //#5. Получить результаты выполнения, если требуется WorkImpl workImpl= (WorkImpl)workItem.getResult(); Page  65 65
  • 66. Контекст выполнения задач Для POJO задач  Задача выполняется с тем же контекстом безопасности  Java:comp вызывающей компоненты доступен в задаче  Можно использовать UserTransaction  Можно использовать удаленное выполнение Для EJB задач  Это обязательно должна быть @Local ссылка на @Stateless session bean  Задача выполняется с тем же контекстом безопасности и он может быть переопределен в EJB  Можно использовать декларативные транзакции  Используется java:comp enterprise bean’а Page  66 66
  • 67. Удаленное выполнение задач JSR-237 WorkManager может выполнять задачи на удалённых JVM:  Work объект должен реализовывать Serializable  Эта функциональность зависит от сервера приложений  Реализовано в CommonJ Page  67 67
  • 68. Java Messaging System Java Message Service (JMS) — стандарт middleware для рассылки сообщений, позволяющий приложениям, выполненным на платформе J2EE, создавать, посылать, получать и читать сообщения. Может использоваться как транспорт для  вызова внутренних компонет  удаленного вызова  вызова SOAP веб сервисов Можно использовать как синхронно, так и асинхронно Page  68 68
  • 69. Java Messaging System Преимущества JMS:  Надежность  Гарантированность доставки (поддержка транзакций)  Масштабируемость  Асинхронность Page  69 69
  • 70. Отправка JMS сообщения @Resource(mappedName="jms/ConnectionFactory") private static ConnectionFactory connectionFactory; @Resource(mappedName="jms/Queue") private static Queue queue; connection = connectionFactory.createConnection(); session = connection.createSession(true, Session.SESSION_TRANSACTED); messageProducer = session.createProducer(queue); message = session.createTextMessage(); for (int i = 0; i < NUM_MSGS; i++) { message.setText("This is message " + (i + 1)); System.out.println("Sending message: " + message.getText()); messageProducer.send(message); } Page  71 71
  • 71. Получение JMS сообщения @MessageDriven(mappedName="jms/Queue", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") }) public class SimpleMessageBean implements MessageListener { public void onMessage(Message inMessage) { TextMessage msg = null; try { if (inMessage instanceof TextMessage) { msg = (TextMessage) inMessage; logger.info("MESSAGE BEAN: Message received: " + msg.getText()); } else { logger.warning("Message of wrong type: " + inMessage.getClass().getName()); } } catch (JMSException e) { e.printStackTrace(); mdc.setRollbackOnly(); } catch (Throwable te) { te.printStackTrace(); } } } Page  72 72
  • 72. Асинхронный вызов EJB В EJB 3.1 появилась простая возможность делать асинхронные вызовы: добавить @Asynchronous аннотацию к методу или всему классу. При вызове такого метода клиент не будет дожидаться окончания выполнения. Page  73 73
  • 73. Асинхронный вызов EJB Существует два вида асинхронных методов: •Метод возвращает void. •Метод возвращает Future<?> @Stateless //@Asynchronous public class AsyncBean { @Asynchronous public void ignoreResult(int a, int b) { // … } @Asynchronous public Future<Integer> longProcessing(int a, int b) { return new AsyncResult<Integer>(a * b); } } Page  74 74
  • 74. EJB Timer Services EJB контейнер предоставляет возможность запускать методы по рассписанию  Можно запускать методы по расписанию, через определенное время, через определенные интервалы  Можно создавать программно, аннотациями или в deployment конфигурации  Таймеры можно создавать в @Stateless, @Singleton и @MessageDriven bean’ах  Таймеры persistent по умолчанию Page  75 75
  • 75. Пример таймера @Singleton @Startup public class DummyTimer3 { @Resource TimerService timerService; @PostConstruct public void initTimer() { if (timerService.getTimers() != null) { for (Timer timer : timerService.getTimers()) { if (timer.getInfo().equals("dummyTimer3.1") || timer.getInfo().equals("dummyTimer3.2")) timer.cancel(); } } timerService.createCalendarTimer( new ScheduleExpression(). hour("*").minute("*").second("*/10"), new TimerConfig("dummyTimer3.1", true)); timerService.createCalendarTimer( new ScheduleExpression(). hour("*").minute("*").second("*/45"), new TimerConfig("dummyTimer3.2", true)); } @Timeout public void timeout(Timer timer) { System.out.println(getClass().getName() + ": " + new Date()); } } Page  76 76
  • 76. Пример таймера EJB 3.1 @Schedules({ @Schedule(hour="*", minute="*", second="*/10", info="every tenth"), @Schedule(hour="*", minute="*", second="*/45", info="every 45th") }) public void printTime(Timer timer) { System.out.println(getClass().getName() + ": " + new Date() + ":" + timer.getInfo()); } Page  77 77
  • 77. Синхронизация методов в EJB Новые возможности в EJB 3.1:  @Singleton – enterprise bean, который реализован как singleton session bean. Существует только один экземпляр bean’а. Можно использовать межпоточную синхронизацию. Для @Singleton bean’ов можно указывать порядок создания:  @Startup – bean инициализируется при запуске приложения  @DependsOn(“MyBean1”, “MyBean2”) – указанные bean’ы должны быть инициализированы до Page  78 78
  • 78. Синхронизация управляемая контейнером @Singleton @AccessTimeout(value=120000) public class BufferSingletonBean { private StringBuffer buffer; @Lock(READ) private String getContent(){ return buffer.toString(); } @Lock(WRITE) public void append(String string) { buffer.append(string); } @Lock(WRITE) @AccessTimeout(value=360000) public void flush { //Save to db ... buffer = new StringBuffer(); } } Page  79 79
  • 79. Программная синхронизация @ConcurrencyManagement(BEAN) @Singleton public class BufferSingletonBean { private StringBuffer buffer; private ReadWriteLock lock = new ReentrantReadWriteLock(); private String getContent(){ try{ lock.readLock().lock(); return buffer.toString(); }finally{ lock.readLock().unlock(); } } public void append(String string) { try{ lock.writeLock().lock(); buffer.append(string); }finally{ lock.writeLock().unlock(); } } public void flush { try{ lock.writeLock().lock(); //Save to db ... buffer = new StringBuffer(); }finally{ lock.writeLock().unlock(); } } } Page  80 80
  • 80. Асинхронный вызов веб сервисов Начиная с JAX_WS 2.0 асинхронный вызов веб сервиса можно просто реализовать на стороне клиента. Клиентский прокси будет сам управлять асинхронным вызовом. Для этого надо: 1. Добавить пользовательский binding 2. Сгенерировать асинхронный клиентский код 3. Вызывать веб сервис через асинхронные методы Page  81 81
  • 81. Генерация клиентского кода для асинхронного вызова Указать пользовательский binding при вызове wsimport <bindings node="wsdl:definitions"> <package name="com.company.jaxws.stockquote.client"/> <enableAsyncMapping>true</enableAsyncMapping> </bindings> Ant задача: <wsimport debug="${debug}" verbose="${verbose}" keep="${keep}" extension="${extension}" destdir="${build.classes.home}" wsdl="${client.wsdl}"> <binding dir="${basedir}/etc" includes="${client.binding.async}" /> </wsimport> Page  82 82
  • 82. Клиентский код @WebService(name = "StockQuote") public interface StockQuote { … public Response<GetQuoteResponse>getQuoteAsync( @WebParam(name = "arg0", targetNamespace = "") String arg0); … public Future<?>getQuoteAsync(String arg0, AsyncHandler<GetQuoteResponse>asyncHandler); … public double getQuote( String arg0); } Page  83 83
  • 83. Вызов веб сервиса //#1 Response<GetQuoteResponse>resp = port.getQuoteAsync (code); while( ! resp.isDone()){ //some client side processes } GetQuoteResponse output = resp.get(); //#2 port.getQuoteAsync ("MHP", new GetQuoteCallbackHandler (){ private GetQuoteResponse output; public void handleResponse (Response<GetQuoteResponse>response) { try { output = response.get (); } catch (ExecutionException e) { e.printStackTrace (); } catch (InterruptedException e) { e.printStackTrace (); } } ); Page  84 84
  • 84. Асинхронный ответ в сервлете @WebServlet("/foo" asyncSupported=true) public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) { ... AsyncContext aCtx = request.startAsync(req, res); ScheduledThreadPoolExecutor executor = new ThreadPoolExecutor(10); executor.execute(new AsyncWebService(aCtx)); } } public class AsyncWebService implements Runnable { AsyncContext ctx; public AsyncWebService(AsyncContext ctx) { this.ctx = ctx; } public void run() { // Какие-либо действия ctx.dispatch("/render.jsp"); } } Page  85 85
  • 85. Полезная литература по теме  Concurrency in Practice, Brian Goetz, Doug Lea, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes  Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects, F. Buschmann, K.Henney, D. Schmidt, M. Stal, H. Rohnert  Patterns in java, Mark Grand  Concurrent Programming in Java, Design Principles and Patterns, Doug Lea  Patterns for Parallel Programming, T.Mattson, B.Sanders, B. Massingill Page  86 86
  • 86. Интернет ресурсы  Leveraging EJB Timers for J2EE Concurrency http://www.devx.com/Java/Article/33694/1954  The Work Manager API: Parallel Processing Within a J2EE Container http://www.devx.com/Java/Article/28815/1954  Simple Asynchronous methods in EJB 3.1 http://javahowto.blogspot.com/2010/03/simple-asynchronous- methods-in-ejb-31.html  Java Memory Model http://gee.cs.oswego.edu/dl/cpj/jmm.html Page  87 87
  • 87. Интернет ресурсы  Double-checked locking http://www.ibm.com/developerworks/java/library/j- dcl/index.html  Non-blocking algorithms http://www.ibm.com/developerworks/java/library/j-jtp04186/  Fork/Join framework http://www.oracle.com/technetwork/articles/java/fork-join- 422606.html http://www.ibm.com/developerworks/java/library/j- jtp03048/index.html Page  88 88

Notes de l'éditeur

  1. Нефункциональные требованияПотребности для распарраллеливания вычислений:Увеличение производительности за счет равномерного использования нескольких процессоровОбработка больших объемов данных Эффективная загрузка процессора, если слабое место – данные, но работу с ними можно вести параллельно. Например работа с данными из разных испочников с данными которые можно обрабатывать параллельно и в конце получить цельный результатДолгие вычисленияСистема становится масштабируемой, если вычисления хорошо распараллеливаются, а данные позволяют параллельную обработкуOf the various aspects of performance, the &quot;how much&quot; aspects 􀍲 scalability, throughput, and capacity 􀍲 are usually of greater concern for server applications than the &quot;how fast&quot; aspects.Масштабируемость системы зависит от распараллеливаемостиAvoid premature optimization. First make it right, then make it fast 􀍲 if it is not already fast enough.
  2. Может исходить из функциональных требований к системе, например:Система должна быть многопользовательскойМногозадачность (пользователь может запускать несколько задач одновременно в системе)Выполнение каких-либо действий в фоновом режиме (проигрывание фильмов, музыки)Выполнение каких-либо действий по расписанию
  3. The J2EE design revolves around the request/response paradigm. For a login request, a user typically provides a user name and password to the server and waits for a response to get access to the site. A J2EE container can serve multiple users at the same time (in parallel) by managing a pool of threads, but for various reasons opening independent threads within a single J2EE container is not recommended. Some containers&apos; security managers will not allow user programs to open threads. Moreover, if some containers allowed opening threads, then they would not manage those threads and therefore no container-managed services would be available for the threads. That would leave you to implement these services manually, which is tedious and liable to add complexity to your code.
  4. Различия небольшиеПример использования:Нужно объединить данные из разных источников для отображения на одной странице. Например через сторонние вебсервисы.
  5. WorkManager=ExecutorServiceWork=Runnable/CallableWorkItem=FutureWorkEvent=
  6. Через консоль
  7. Коммуникация между компонентами, использующими JMS, асинхронна (процедура не дожидается ответа на своё сообщение) и независима от исполнения компонентов.JMS - транспорт
  8. Коммуникация между компонентами, использующими JMS, асинхронна (процедура не дожидается ответа на своё сообщение) и независима от исполнения компонентов.
  9. @Singleton@Asynchronouspublic class AsyncBean { @Asynchronous //this line can be omittedpublic void ignoreResult(int a, int b) { // the client doesn&apos;t care what happens here } @Asynchronous //Аннотациpublic Future&lt;Integer&gt; longProcessing(int a, int b) {return new AsyncResult&lt;Integer&gt;(a * b); }}
  10. Все клиенты вызывают методы одного экземпляраspec does not address &quot;high-end&quot; features like clustering, load-balancing and fail-over. However, I think this is a valuable comment to send to the EG comments email alias.As far as I know, major vendors do plan to implement clustering, load-balancing and fail-over for EJB Singletons, so you should have your wish :-).
  11. One of the significant enhancements made in JSR 315: Java Servlet 3.0, is support for asynchronous processing. With this support, a servlet no longer has to wait for a response from a resource such as a database before its thread can continue processing, that is, the thread is not blocked. Previous to Servlet 3.0, asynchronous support in the Java EE web container was provided in a proprietary way — either through APIs built on top of the Servlet 2.5 API or through non-Servlet APIs or implementations.In modern web applications there are times when you need to asynchronously handle some part of the request, so that the web container can continue serving other requests in a seamless fashion. One example is a chat room application. In this type of application you want to enable long-lived client connections with a servlet. You don&apos;t want a server thread to be blocked for a long period of time serving a request from a single client. You want the servlet to process a request from the client and then free up the server thread as quickly as possible for other work. In other words, you want the request to be processed and a response generated asynchronously.With the upcoming release of the Servlet 3.0 specification, standard asynchronous support has been added to the Servlet API. This Tech Tip introduces the asynchronous support that has been added to the Servlet API in Java Servlet 3.0 technology. It also includes a sample application that demonstrates those features.