java.util.concurrency
Wielowątkowość z punktu widzenia Java EE, Spring, Akka
ericpol.com
Ericpol
rrrr-mm-dd 2
• Ponad 2000 pracowników w 4 krajach
• Ericpol Sp. z o.o. • Własność prywatna • Założona w 1991
• Obroty 2013: 66,5 MEUR
• Oddziały: • Linköping, Szwecja • Lwów, Ukraina • Brześć, Białoruś
• Certyfikat ISO 9001 & 14001
• Siedziba: Łódź, Polska • Biura: Kraków, Warszawa
ericpol.com
Ericpol w liczbach
Ericpol w
liczbach
Ponad
75 krajów, w których
realizowaliśmy projekty
Ponad
750 zrealizowanych
projektów
Ponad
2 mld ludzi korzystających ze współtworzonego
przez nas oprogramowania
Ponad
1mln samochodów z naszym
oprogramowaniem
rrrr-mm-dd 3
ericpol.com
Obszary biznesowe
Bankowość i Finanse
Aplikacje dla biznesu M2M
Aplikacje medyczne
rrrr-mm-dd 4
Zamówienia publiczne
§ Integracja
§ Rozwiązania
dedykowane
§ E-usługi
§ Obieg
dokumentów
§ Wynajem kadry
§ Utrzymanie
i rozwój
oprogramowania
§ Rozwiązania
dedykowane
§ Wdrożenia
oprogramowania
§ Szkolenia
§ Wdrożenia
§ Rozwój
§ Kastomizacja
§ Dedykowane
rozwiązania IT
§ Utrzymanie
§ Szkolenia
§ Konsulting
§ Konsulting
§ Migracja
§ Wynajem kadry
§ Integracja
§ Rozwój
oprogramowania
§ Utrzymanie
§ Rozwiązania
własne: drEryk,
erLab, aplikacje
mobilne
§ Kastomizacja
§ Szkolenia
Telekomunikacja
§ Wynajem kadry
§ Konsulting
§ Kastomizacja
§ Rozwiązania
dedykowane
§ Szkolenia
§ Integracja
§ Rozwój
ericpol.com
Pokrótce omówimy
THREAD
JSE
JEE
Runnable
Future
Executors
ThreadPool
JEE 6
JEE 7
@Asynchronous
Components Pool
ManagedExecutors
ManagedThreadPools
Connector Thread Pool
Asynchronous
ericpol.com
Każdy w życiu czasem chce zrobić coś dużego…
ericpol.com
No to budujmy…
ericpol.com
A dałoby się szybciej?
ericpol.com
Najlepiej jakby się dało…
ericpol.com
Ale jak to mówią…
9 kobiet nie urodzi w jeden miesiąc
ericpol.com
Potrzebna koordynacja prac
ericpol.com
Inaczej efekt może być inny niż oczekiwany
?
ericpol.com
Aplikacja
ericpol.com
Przetwarzanie żądań
Pula wątków odbierających żądania
ericpol.com
Czasami nasze niektóre zadania…
są cięższe niż wyświetlenie buźki na ekranie….
ericpol.com
… i potrafią przytkać system…
Pula połączeń
ericpol.com
… lub wyżreć całą pamięć…
Pamięć
ericpol.com
W oczekiwaniu na wynik
ericpol.com
Co można poradzić
dołożyć sprzętu?
dołożyć pamięci?
ericpol.com
Ograniczmy żarłoczność aplikacji
ericpol.com
Środowisko
§ JSE - w zasadzie ręczne zarządzanie wątkami
§ JEE - wątki zarządzane przez serwer - nie zalecane ręczne uruchamianie wątków
- nowe elementy w JEE 7
ericpol.com
Dla przypomnienia
@FunctionalInterface public interface Runnable {
public abstract void run();
}
public class MyRunnable implements Runnable {
@Override public void run() {
}
}
ericpol.com
public class MyThread extends Thread{
public MyThread() {
super(new MyRunnable()); }
}
ericpol.com
Dla przypomnienia c.d.
Thread thread = new Thread(new MyRunnable());
thread.start();
Thread thread = new MyThread();
thread.start();
ericpol.com
Lock
§ Lock § ReentrantLock
§ ReentrantReadWriteLock
ericpol.com
ThreadPool
pula wątków
Potraktujmy pulę wątków jak pulę połączeń. Spowodujemy iż określone zadanie będzie przeprowadzane tylko przez określoną ilość wątków. Dzięki temu zapanujemy np. nad zużyciem pamięci i zablokujemy nadmierną pazerność aplikacji (jeśli takowa istnieje).
ericpol.com
ExecutorService
ExecutorService executorService = Executors.newFixedThreadPool(5);
ericpol.com
ExecutorService
ExecutorService executorService = Executors.newFixedThreadPool(10);
ExecutorService executorService =
Executors.newCachedThreadPool( new ThreadFactory() {
@Override public Thread newThread(Runnable r) { return ….. ; }
} );
ericpol.com
Callable<V> i Future<V>
public interface Callable<V> { V call() throws Exception; } public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
ericpol.com
Wywołanie zadania
ExecutorService executorService = Executors.newFixedThreadPool(10);
Future<String> future =
executorService.submit( new Callable<String>() { @Override public String call() throws Exception { executorService.invoke();
return "TEST"; }
} );
ericpol.com
Zbieranie wyników
ExecutorService executorService = Executors.newFixedThreadPool(5);
CompletionService completion = new
ExecutorCompletionService(executorService); for(;;){
completion.take(); }
ericpol.com
ForkJoinPool
§ Mechanizm wprowadzony w Java 7
§ java.util.concurrent.ForkJoinPool
§ java.util.concurrent.ForkJoinTask<V> § java.util.concurrent.RecursiveTask<V>
§ java.util.concurrent.RecursiveAction
ericpol.com
ForkJoinPool
ForkJoinPool pool = new ForkJoinPool();
ForkJoinPool pool = new ForkJoinPool(
Runtime.getRuntime().availableProcessors() );
ericpol.com
ForkJoinTask
ForkJoinPool pool = new ForkJoinPool();
pool.execute(
new ForkJoinTask<String>{
} );
pool.execute(
ForkJoinTask.adapt(Callable<String>){
} );
ericpol.com
RecursiveTask
class Incrementor extends RecursiveTask<Integer> { int theNumber;
Incrementor(int x) {
theNumber = x; }
public Integer compute() { return theNumber + 1;
}
}
ericpol.com
RecursiveTask (2)
class Sum extends RecursiveTask<Long> {
Sum(int[] arr, int lo, int hi) {
array = arr; low = lo;
high = hi; }
protected Long compute() { …
}
}
ericpol.com
Fork & Join
protected Long compute() {
if(high - low <= SEQUENTIAL_THRESHOLD) { long sum = 0;
for(int i=low; i < high; ++i)
sum += array[i];
return sum;
} else {
int mid = low + (high - low) / 2;
Sum left = new Sum(array, low, mid);
Sum right = new Sum(array, mid, high); left.fork();
long rightAns = right.compute();
long leftAns = left.join();
return leftAns + rightAns;
}
}
ericpol.com
Wątki a JavaEE
§ JavaEE <=6 Brak bezpośredniej możliwości tworzenia i zarządzania wątkami.
§ Można wykorzystać niestandardowe mechanizmy serwerów w zakresie konfiguracji - JMS - Pule wątków (connector HTTP) - Pule komponentów (EJB) - @Singleton
§ Java EE 7 - Concurrency Utilities for Java EE (JSR 236)
ericpol.com
Sterowanie
§ Globalne - pule wątków konektorów serwera
§ Lokalne - pule komponentów - pule wątków
ericpol.com
EJB
ericpol.com
maxSize=5
ericpol.com
maxSize=1
ericpol.com
Pule komponentów EJB
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool"
max-pool-size="20"
instance-acquisition-timeout="5"
instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="mdb-strict-max-pool"
max-pool-size="20" instance-acquisition-timeout="5"
instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
ericpol.com
subsystem xmlns="urn:jboss:domain:ejb3
<session-bean> <stateless>
<bean-instance-pool-ref
pool-name="slsb-strict-max-pool"/> </stateless>
</session-bean>
<mdb>
<bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
</mdb>
ericpol.com
jboss-ejb3.xml
§ Plik pozwala na zmianę domyślnej konfiguracji kontenera ejb dla poszczególnych komponentów wdrażanych w ramach aplikacji.
§ Konfiguracja może wykorzystywać ustawienia z zakresu namespace m.in. - urn:clustering
- urn:security - urn:iiop - urn:ejb-pool - urn:ejb-cache
ericpol.com
Przykład
<?xml version="1.1" encoding="UTF-8"?> <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee" …>
<assembly-descriptor> <p:pool>
<ejb-name>*</ejb-name> <p:bean-instance-pool-ref>test</p:bean-instance-pool-ref>
</p:pool>
</assembly-descriptor>
</jboss:ejb-jar>
ericpol.com
@Singleton
ericpol.com
@Singleton
ericpol.com
@Singleton
@ConcurrencyManagement(CONTAINER) @Singleton public class ExampleSingletonBean {
private String state;
@Lock(READ) public String getState() {
return state;
}
@Lock(WRITE) public void setState(String newState) {
state = newState;
}
}
ericpol.com
@Singleton
@ConcurrencyManagement(CONTAINER) @Singleton @Lock(READ) public class ExampleSingletonBean {
private String state;
public String getState() {
return state;
}
@Lock(WRITE) public void setState(String newState) {
state = newState;
}
}
ericpol.com
@Singleton
@ConcurrencyManagement(CONTAINER) @Singleton @Lock(READ) @AccessTimeout(value=360000) public class ExampleSingletonBean {
private String state;
public String getState() {
return state;
}
@Lock(WRITE) public void setState(String newState) {
state = newState;
}
}
ericpol.com
Concurrency Utilities for Java EE (JSR 236)
Application Server
ManagedExecutorService
ManagedScheduledExecutorService
ContextService
ManagedThreadFactory
ericpol.com
Konfiguracja
<subsystem xmlns="urn:jboss:domain:ee:2.0">
<concurrent> <context-services>
…
</context-services>
<managed-thread-factories>
…
</managed-thread-factories>
<managed-executor-services>
… </managed-executor-services>
<managed-scheduled-executor-services>
…
</managed-scheduled-executor-services>
</concurrent>
</subsystem>
ericpol.com
public class ReportTask implements Callable<Report>{
public void run() {
try {
Thread.sleep(3000); } catch (InterruptedException e) {
} }
}
ericpol.com
ContextService
@Stateless public class ReportBean {
@Resource private ContextService contextService;
public void runReports() {
ReportTask reportTask = new ReportTask();
Callable<Report> report = contextService.
createContextualProxy( new ReportTask(), Callable.class); }
}
ericpol.com
ManagedThreadFactory
@Stateless public class ReportBean {
@Resource(
lookup="java:jboss/ee/concurrency/factory/MyManagedThreadFactory")
private ManagedThreadFactory threadFactory;
public void runReports() {
ReportTask reportTask = new ReportTask();
Thread thread = threadFactory.newThread(reportTask); thread.start();
}
}
ericpol.com
ManagedExecutorService
@Stateless public class ReportBean {
@Resource private ManagedExecutorService executorService;
public void runReports() {
ReportTask reportTask = new ReportTask();
Future<Report> future = executorService.submit(reportTask);
} }
ericpol.com
CustomExecutorService
@Singleton public class ExecutorAccessor { private ExecutorService threadPoolExecutor = null;
@Resource(name="concurrent/ThreadFactory")
ManagedThreadFactory threadFactory;
@PostConstruct public void postConstruct() {
threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(10), threadFactory); }
public ExecutorService getThreadPool() {
return threadPoolExecutor;
}
}
ericpol.com
ManagedScheduledExecutorService
@Stateless public class ReportBean {
@Resource(
lookup=
"java:jboss/ee/concurrency/scheduler/MyScheduledExectutorService")
private ManagedScheduledExecutorService executorService;
public void runReports() {
ReportTask reportTask = new ReportTask(); executorService.scheduleAtFixedRate(reportTask, 0L, 1L, TimeUnit.HOURS);
}
}
ericpol.com
JMS
ericpol.com
JMS
ericpol.com
JMS