SlideShare a Scribd company logo
JAVA EE CONCURRENCY MISCONCEPTIONS
Haim Yadid, Performize-IT Ltd.
Daniel Pfeifer, Whistler AB
Daniel Pfeifer

‣ Founder of
Performize-IT Ltd.
‣ 18+ years in
technology
‣ Primary expertise in
performance optimization

‣ Founder of
Whistler AB
‣ 10+ years in IT
‣ Primary expertise in missioncritical business applications

WHO ARE THOSE GUYS?

Haim Yadid
JAVA EE IN THE MULTIPROCESSOR ERA
OPTIMISM

Moore’s Law:
The amount of transistors
appx. doubles every second
year
JAVA EE IN THE FUTURE

That’s why Multi core
hardware will become
mainstream for JEE servers
18"
16"
14"
12"
10"

CPUs/server"

8"

CPUs/phone"

6"

CPUs/notebook"

4"
2"
0"
2006"

2008"

2010"

2012"

IS MULTICORE NEW TO JAVA EE?

Budget machines
A FRIENDLY ADVICE

Don’t do it yourself !!
There is an App Server for that
TOOLS OF TRADE

‣ ”Local" and cluster-wide load balancing	
‣ Message driven beans for parallelization / async tasks	
‣ Asynchronous annotations	
‣ Automatic and bean managed concurrency 	
‣ Resource management
6 REAL LIFE EXAMPLES
SYNCHRONIZATION IN EJB
You found yourself in need of sharing some data between calls so you
‣ Create a static constant pointing to a List (or perhaps your own
singleton)
‣ Add a synchronization block for your constant
‣ You operate on your instance inside the synchronize-block

SYNCHRONIZATION IN ENTERPRISE BEANS

Use Case
@Stateless
public class SharedStateEJB {
private static final List usedNumbers = new ArrayList();
public double fetchUnusedRandomNumber() {
double number = 0d;
synchronized (usedNumbers) {
while (true) {
number = Math.random();
if (!usedNumbers.contains(number)) {
usedNumbers.add(number);
break;
}
}
}
return number;
}
}

SYNCHRONIZATION IN ENTERPRISE BEANS

Returning unused random numbers
Sharing state like this will not work, because …
‣ Static constants are not shared among class loaders
‣ A lock will not is not propagated across machines

SYNCHRONIZATION IN ENTERPRISE BEANS

Problems
SYNCHRONIZATION IN ENTERPRISE BEANS

What about Java EE Singleton?
@Singleton
public class UsedNumbersBean {
private final List usedNumbers = new ArrayList();
@Lock(READ)
public boolean numberExists(double num) {
return usedNumbers.contains(num);
}
@Lock(WRITE)
public void addNumber(double num) {
usedNumbers.add(num);
}
}

SYNCHRONIZATION IN ENTERPRISE BEANS

@Singleton
“Backup” solutions
‣ Use the database and use locking => Potentially slow
‣ Use a cluster-aware cache (i.e. EHCache or JBoss Cache)
‣  Read the chapters on clusters and consistency!
‣ Terracotta
“Creative” solutions
‣ Use a single EJB
‣ Use H/A Singleton (available on JBoss)
‣ Wait for the future…

SYNCHRONIZATION IN ENTERPRISE BEANS

Suggestions
ASYNCHRONICITY THROUGH THREADS
•  You processed an order
•  You ask the bank for settlement confirmation
•  You can present the customer with a result without waiting for the
bank

ASYNCHRONICITY THROUGH THREADS

Use Case
@Stateless
public class OrderHandlingBean {
public String process(final Order order) {
String orderId = ...//save order to database and get id
final Thread t = new Thread() {
@Override public void run() {
// submit amount to bank
}
};
t.start(); // start “background” process
return orderId;
}
}

ASYNCHRONICITY THROUGH THREADS

Creating a thread for async tasks
‣ Enough stuck Threads will eventually make your server go OOM.
‣ Difficult to get transaction management right.
‣  Some servers will tell you it can’t check the status, some don’t.
‣  Failed tasks in the thread need difficult manual rollback.
‣ Threads do not scale out
‣  Can’t be load-balanced to other machines.
‣  Server’s automatic resource management doesn’t cover your own
threads.
‣ Debugging and monitoring isn’t the joy it used to be.

ASYNCHRONICITY THROUGH THREADS

Problems
1.8
1.6

Response Time

1.4
1.2
1

java.lang.OutOfMemoryError: unable to create
new native thread
Async

0.8

Sync

0.6
0.4
0.2
0
1h

4h

7h

10h
13h
Runtime

16h

19h

ASYNCHRONICITY THROUGH THREADS

Thread bugs gone wild
‣ Until Java EE 6 Message Driven Beans are used for asynchronous
tasks.
‣ And if you are lucky enough to use a Java EE 6 container, you can
use the new @Asynchronous.

ASYNCHRONICITY THROUGH THREADS

Best Practice Alternatives
@Stateless(name = ”QueueingEJB")
public class QueueingBean {
@Resource private Queue q;
@Resource private ConnectionFactory cf;
public String process(final Order order) {
// ... saving the Order to the database and fetching id
Connection cn = connectionFactory.createConnection();
Session s = cn.createSession(true, AUTO_ACKNOWLEDGE);
MessageProducer producer = s.createProducer(queue);
Message msg = s.createTextMessage(payment);
producer.send(msg);
return orderId;
}
}

Don’t forget clean-up!
We just want to
conserve screen estate!

ASYNCHRONICITY THROUGH THREADS

Using Queues
@MessageDriven(name = “PayEJB”,
activationProperties = {
/* activation properties for your server */
})
public class PayBean implements MessageListener {
public void onMessage(Message m) {
// Calling bank...
}
}

ASYNCHRONICITY THROUGH THREADS

Using Queues
@Stateless(name = ”PayEJB")
public class PayBean{
@Asynchronous
public void callBank(final String payment) {
// Hello, ... Bank!
}
}

ASYNCHRONICITY THROUGH THREADS

Using @Asynchronous
@Stateless(name = ”AsyncCallerEJB")
public class AsyncCallerBean {
@EJB private PayBean payBean;
public String process(final Order order) {
// ... saving the Order to the database and fetching id
payBean.callBank(payment);
return orderId; // <- Returns + transaction OK
}
}

That’s All!!!

ASYNCHRONICITY THROUGH THREADS

Using @Asynchronous
We mentioned transactions…
‣ True, our examples won’t use the same Transaction, but…
‣  @Asynchronous will by spec create a Transaction
(REQUIRES_NEW)
‣  MDBs will also create a transaction

ASYNCHRONICITY THROUGH THREADS

A note for the observant
PARALLELISM WITH THREAD POOLS
Your back-office staff fires off a bunch of invoices and you want the
total as fast as possible, so you…
‣ Create a thread-pool
‣ Push all invoices for calculation to the thread-pool
‣ Wait for the answer and return it

PARALLELISM WITH THREADPOOLS

Use Case
private static class OrderCallable implements Callable<Double> {
private final Order order;
public OrderCallable(Order order) {
this.order = order;
}
@Override
public Double call() throws Exception {
// return the total based on the order that’s been
// provided.
}
}

PARALLELISM WITH THREADPOOLS

Parallelizing with a ThreadPool (our Callable)
public double processOrders(List<Order> orders) {
ExecutorService executorService =
Executors.newFixedThreadPool(10);
List<Future<Double>> futures = new ArrayList<>();
for (Order order : orders) {
OrderCallable callable = new OrderCallable (order);
callables.add(callable);
futures.add(executorService.invoke (callable));
}
double totalValue = 0;
try {
for (Future<Double> future : futures) {
totalValue += future.get(10, SECONDS);
}
} catch (TimeoutException e) {
return -1;
}
return totalValue;
}

PARALLELISM WITH THREADPOOLS

Parallelizing with a ThreadPool (using the Callable in an ExecutorService)
Essentially we got the same problems as previously, but…
‣ Potential for much larger thread leaks
‣ Still not covered by transaction
‣ Executors, just like Threads, won’t run tasks on other machines.
‣ There is nothing H/A about this.
‣  On crash, part or all of the workload is gone.
‣  Can’t be resumed on server restart, it’s just gone…

PARALLELISM WITH THREADPOOLS

Problems
‣ Up to and including Java EE 5 you can use MDBs
‣  Queues can be clustered, so other servers can take some of the
load.
‣ @Asynchronous-annotated method returning Future

PARALLELISM WITH THREADPOOLS

Pure Java EE alternatives
Using @Asynchronous (invokee)
@Stateless
@Asynchronous
public class ProcessBean {
public Future<Double> getTotals(Order order) {
double value = // .. Calculate value;
return new AsyncResult<Double>(value);
}
}
@Stateless public class OrderBean {
@EJB private ProcessBean processBean;
public double parallelizeCalculationAsync(List<Order> orders) {
List<Future<Double>> futures = new ArrayList<>();
for (Order order : orders) {
futures.add(processBean.getTotals(order));
}
double totalValue = 0;
try {
for (Future<Double> future : futures) {
totalValue += future.get(10, SECONDS);
}
} catch (Exception e) {
// ignore
}
return totalValue;
}
}

PARALLELISM WITH THREADPOOLS

Using @Asynchronous (invoker)
@Stateless public class OrderBean {
@Resource(mappedName = “ConnectionFactory”) private ConnectionFactory cf;
@Resource(mappedName = “RequestQ”)
private Destination sendQueue;
@Resource(mappedName = “ResponseQ”)
private Destination responseQueue;
@TransactionAttribute(NOT_SUPPORTED) // or UserTransaction
public double handleOrders(List<Order> orders) {
try {
// …create a producer
for (Order o : orders) {
ObjectMessage outgoing = s.createObjectMessage();
outgoing.setObject(o);
outgoing.setLongProperty(“RequestID”, orders.hashCode())
mp.send(outgoing);
}
cn.start(); // must be started, otherwise we can't receive
MessageConsumer mc = s.createConsumer(responseQueue,
"JMSCorrelationID = '" + orders.hashCode() + "'");
double totalValue = 0;
for (int i = 0; i < orders.length(); i++)
totalValue += mc.receive(10, SECONDS).getDoubleProperty(“OrderValue”);
return totalValue;
} catch (JMSException e) {
throw new EJBException(e);
}
}
}

Send

Receive

PARALLELISM WITH THREADPOOLS

Using MDB (invoker)
@MessageDriven(mappedName = “RequestQ”)
public class ProcessOrderBean implements MessageListener {
@Resource(mappedName = “ConnectionFactory")
private ConnectionFactory cf;
@Resource(mappedName = “ResponseQ")
private Queue responseQueue;
public void onMessage(Message message) {
double orderValue = // ... Process order
try {
MessageProducer mp = // … create message producer
Message msg = s.createMessage();
msg.setJMSCorrelationID(message.getIntProperty(“RequestID”));
msg.setDoubleProperty(”OrderValue”, orderValue);
mp.send(msg);
} catch (JMSException e) {
throw new EJBException(e);
}
}
}

PARALLELISM WITH THREADPOOLS

Using MDB (invokee)
PARALLELISM WITH THREADPOOLS

A nice write up, but is it worth it?
12000
10000
8000
1 user

6000

10 users
20 users

4000
2000
0
Serial

8 parallel

PARALLELISM WITH THREADPOOLS

Response time – Compute intensive Tasks
FORK AND KNIVES… UHM… JOIN
‣ New to Java 7 java.util.concurrent
‣ Helps you write a parallel recursive algorithm
‣ Break a long task to Fine grained tasks
‣ Very efficient for relatively short tasks

FORK JOIN

Introduction
ForkJoinTask

FORK JOIN

Introduction

ForkJoinPool

Worker
Worker
Worker

Worker
class PartialTask extends RecursiveAction {
protected void compute() {
PartialTask pt1 = new PartialTask(firstHalf);
PartialTask pt2 = new PartialTask(secondHalf);
pt1.fork(); // fork
pt2.exec(); // execute in new thread
pt1.join(); // wait for completion
}
}
fjPool = new ForkJoinPool(para);
Para.invoke(task)

FORK JOIN

Example
‣ Divide n points into k clusters
‣ Based on proximity

FORK JOIN

A Benchmark K-Means Clustering Algorithm
‣ This is not a formal benchmark
‣ I tried to do my best but it is not community criticized
‣ Ran on 8 core machine (no HT)
‣ Windows OS
‣ Warm-up was taken into account J
‣ 120K points to 50 clusters

FORK JOIN

Disclaimer
FORK JOIN

Response Time – by amount of parallelism
6000"

5000"

Time%(sec)%

4000"

3000"
Time"
2000"

1000"

0"
1"

2"

3"

4"

5"
#cores%used%

6"

7"

8"
FORK JOIN

Speedup– by amount of parallelism
6"

5"

Time%(sec)%

4"

3"
Speedup"
2"

1"

0"
1"

2"

3"

4"

5"
#cores%used%

6"

7"

8"
FORK JOIN

Single Operation Throughput

Op/sec'
1"
0.8"
0.6"
Op/sec"

0.4"
0.2"
0"
1"

2"

3"

4"

5"

6"

7"

8"
‣ Does your server need to do anything else ?
‣ Selfish Task Deplete all compute resources slows other task
‣ What about throughput

FORK JOIN

FJ on a JEE Server
FORK JOIN

What About Throughput ?
Lets check !
‣ What will be better

FORK JOIN

Throughput of 8 Concurrent Users
FORK JOIN

Throughput 8 concurrent users in parallel

Op/sec'
1.8"
1.6"
1.4"
1.2"
1"
0.8"
0.6"
0.4"
0.2"
0"

Op/sec"

Serial"Algorithm"

Fork"Join"
Parallelism"1"

Fork"Join"
Parallelism"8"
FORK JOIN

Response Time

9000"
8000"
7000"
6000"
5000"
4000"
3000"
2000"
1000"
0"

TRT"of"8"Users"
TRT"of"1"User"

Serial"
Algorithm"

Fork"Join"
Fork"Join"
Parallelism"1" Parallelism"8"
‣ Use FJ for the non common case
‣ Limit the number of cores do not starve other server tasks

FORK JOIN

Conclusion
LOAD MANAGEMENT FOR BACKEND ACCESS
You have a backend machine that can only handle 20 concurrent
requests and you have a cluster of four servers, so you…
‣ Create a semaphore with five permits.
‣ Acquire lock on semaphore
‣ Call server
‣ Release lock

LOAD MANAGEMENT FOR BACKEND ACCESS

Use Case
‣ The backend server can be under-utilized across the cluster.
‣  First server could be full of locks while second is free.
‣ One server can stall unnecessarily long time.
‣ Recompile necessary if some parameter changes.

LOAD MANAGEMENT FOR BACKEND ACCESS

Problems With This Approach
Using the Request-Reply Pattern (EIP), using:
‣ Clustered queues (request + response)
‣ A caller (stateless session bean)
‣ A backend invoker bean (message-driven bean)
‣ Configuration to limit in-process messages
For the advanced:
‣ Write a resource adapter (JCA)
‣  Support load balancing
‣  Support cluster

LOAD MANAGEMENT FOR BACKEND ACCESS

A Better Approach
@Stateless public class DispatcherBean {
@Resource(mappedName = “ConnectionFactory”) private ConnectionFactory cf;
@Resource(mappedName = “RequestQ”)
private Destination sendQueue;
@Resource(mappedName = “ResponseQ”)
private Destination responseQueue;
@TransactionAttribute(NOT_SUPPORTED) // Alternatively UserTransaction
public double checkStockRate(String stockName) {
try {
//… create producer
Message outgoing = s.createMessage();
outgoing.setStringProperty(”StockName", stockName);
mp.send(outgoing);

Send

String correlationId = outgoing.getJMSMessageID();
cn.start(); // must be started, otherwise we can't receive
MessageConsumer mc = s.createConsumer(responseQueue,
"JMSCorrelationID = '" + correlationId + "'");
Message incoming = mc.receive(10000L); // wait no more than 10 seconds
if (incoming != null) {
return incoming.getDoubleProperty(”StockPrice");
} else {
return Double.MIN_VALUE;
}
} catch (JMSException e) {
throw new EJBException(e);
}
}
}

Receive

LOAD MANAGEMENT FOR BACKEND ACCESS

Request-Reply Pattern using clustered queues (Caller SLSB)
@MessageDriven(mappedName = “RequestQ”)
public class BackendInvokerBean implements MessageListener {
@Resource(mappedName = “ConnectionFactory")
private ConnectionFactory cf;
@Resource(mappedName = “ResponseQ")
private Queue responseQueue;
public void onMessage(Message message) {
double stockPrice = // ... Fetch from backend service
try {
// … create producer
Message msg = s.createMessage();
msg.setJMSCorrelationID(message.getJMSMessageID());
msg.setDoubleProperty(”StockPrice”, stockPrice);
mp.send(msg);
} catch (JMSException e) {
throw new EJBException(e);
}
}
}

LOAD MANAGEMENT FOR BACKEND ACCESS

Request-Reply Pattern using clustered queues (Invoker MDB)
Vendor-specific, but in general:
‣ You may set an upper limit on consumers
‣  Glassfish has maxNumActiveConsumers
‣ You may set an upper limit of MDBs in Pool
‣  Works on all servers regardless of vendor (i.e. set max-poolsize to 5 in glassfish-ejb-jar.xml)

LOAD MANAGEMENT FOR BACKEND ACCESS

Configuration for in-process limitation
LOAD MANAGEMENT FOR BACKEND ACCESS

Isn’t MDB horribly slow?
12
10
8
1 user

6

5 users
10 users

4
2
0
Direct

MDB

LOAD MANAGEMENT FOR BACKEND ACCESS

Response time (in milliseconds)
INTERFERING WITH BEAN POOL
You occasionally suffer from resource depletion so to protect your
server you:
‣ Create an EJB Interceptor that
‣  checks current beans in use (i.e. through counter or MBeans)
‣  throws an exception at chosen maximum size.
‣  Or wait until level go down
‣ Assign it to your EJB.

INTERFERING WITH BEAN POOL

Use Case
‣ Is there always equal load distribution across all tasks?
‣ Intelligent load balancers may continue to shoot at the wrong target
‣  It’s just an exception… not an overload
‣ DeadLock

INTERFERING WITH BEAN POOL

Problems
Leave pool management to the server, pool sizes:
‣ Can be tuned on a global level
‣  Right strategy (infinite thread pools, incremental, fixed)
‣  Global default for min/max/timeout
‣ Can be set for each EJB
‣  XML
‣  Annotations (i.e. JBoss)

INTERFERING WITH BEAN POOL

Better approach
It can be configured through the GUI…(Glassfish example)

INTERFERING WITH BEAN POOL

Leave Management to the app server
<glassfish-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>AnEJB</ejb-name>
<bean-pool>
<steady-pool-size>10</steady-pool-size>
<resize-quantity>10</resize-quantity>
<max-pool-size>100</max-pool-size>
<pool-idle-timeout-in-seconds>
60
</pool-idle-timeout-in-seconds>
</bean-pool>
</ejb>
</enterprise-beans>
</glassfish-ejb-jar>

INTERFERING WITH BEAN POOL

Through Config Files
CONCLUSION
CONCLUSION

‣ Most mistakes stem from misunderstanding the app server, try to
understand your app server’s OOTB-capabilities…
‣ …and the Java EE specification.
‣ If you have a valid case for your own concurrency-related code,
make sure it plays well with the container.
‣ Your app server doesn’t always know best, but it often does. And if
not, you can often help it understand!
‣ Do not expect your environment to always look the same, it changes
quicker than you might think.
QUESTIONS?
haim.yadid@gmail.com

Daniel Pfeifer
danpfe@gmail.com

CONTACT INFO

Haim Yadid

More Related Content

PDF
Short intro to scala and the play framework
PDF
Asynchronous web apps with the Play Framework 2.0
PDF
Best Practices - PHP and the Oracle Database
PPT
Reactive Java EE - Let Me Count the Ways!
PDF
Cloud Foundry, Spring and Vaadin
PPTX
Apache Camel: The Swiss Army Knife of Open Source Integration
PDF
the Spring 4 update
PPTX
Java EE 8
Short intro to scala and the play framework
Asynchronous web apps with the Play Framework 2.0
Best Practices - PHP and the Oracle Database
Reactive Java EE - Let Me Count the Ways!
Cloud Foundry, Spring and Vaadin
Apache Camel: The Swiss Army Knife of Open Source Integration
the Spring 4 update
Java EE 8

What's hot (20)

PDF
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
PDF
Atlanta JUG - Integrating Spring Batch and Spring Integration
PDF
Apache Aries Overview
PPTX
Connection Pooling
PPT
Woa. Reloaded
PDF
Java MySQL Connector & Connection Pool Features & Optimization
PPTX
Batching and Java EE (jdk.io)
PDF
Beyond Breakpoints: A Tour of Dynamic Analysis
PDF
Ehcache 3 @ BruJUG
ZIP
Above the clouds: introducing Akka
PDF
Scaling Your Cache
PDF
Apache Commons Pool and DBCP - Version 2 Update
PDF
Building Asynchronous Applications
PDF
a Running Tour of Cloud Foundry
PPTX
Asynchronous Web Programming with HTML5 WebSockets and Java
PDF
System Integration with Akka and Apache Camel
KEY
Hibernate performance tuning
PPTX
Java Play Restful JPA
PDF
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
PPTX
R2DBC Reactive Relational Database Connectivity
JavaCro'14 - Scala and Java EE 7 Development Experiences – Peter Pilgrim
Atlanta JUG - Integrating Spring Batch and Spring Integration
Apache Aries Overview
Connection Pooling
Woa. Reloaded
Java MySQL Connector & Connection Pool Features & Optimization
Batching and Java EE (jdk.io)
Beyond Breakpoints: A Tour of Dynamic Analysis
Ehcache 3 @ BruJUG
Above the clouds: introducing Akka
Scaling Your Cache
Apache Commons Pool and DBCP - Version 2 Update
Building Asynchronous Applications
a Running Tour of Cloud Foundry
Asynchronous Web Programming with HTML5 WebSockets and Java
System Integration with Akka and Apache Camel
Hibernate performance tuning
Java Play Restful JPA
Solving the C20K problem: Raising the bar in PHP Performance and Scalability
R2DBC Reactive Relational Database Connectivity
Ad

Similar to Java Enterprise Edition Concurrency Misconceptions (20)

PDF
OTN Tour 2013: What's new in java EE 7
ODP
Java Concurrency
PPTX
Jakarta Concurrency: Present and Future
PDF
AAI 2236-Using the New Java Concurrency Utilities with IBM WebSphere
PDF
AAI-2236 Using the new Java Concurrency Utilities with IBM WebSphere
ODP
Java Concurrency, Memory Model, and Trends
ODP
Concurrent Programming in Java
PPTX
Java ee7 1hour
PDF
InterConnect 2016 Java EE 7 Overview (PEJ-5296)
PPTX
Getting Started with Java EE 7
PDF
Java EE 7 Recipes for Concurrency - JavaOne 2014
PDF
Concurrency-5.pdf
PDF
Java EE 7 Platform: Boosting Productivity and Embracing HTML5 - Arun Gupta (R...
PDF
Java EE 7: Boosting Productivity and Embracing HTML5
PDF
S314168 - What's New in Enterprise Java Bean Technology @ JavaOne Brazil 2010
PDF
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
PPT
Don't Wait! Develop responsive applications with Java EE7 instead
PDF
Presente e Futuro: Java EE.next()
PPT
JavaOne 2007 - TS4721
PDF
AAI-1713 Introduction to Java EE 7
OTN Tour 2013: What's new in java EE 7
Java Concurrency
Jakarta Concurrency: Present and Future
AAI 2236-Using the New Java Concurrency Utilities with IBM WebSphere
AAI-2236 Using the new Java Concurrency Utilities with IBM WebSphere
Java Concurrency, Memory Model, and Trends
Concurrent Programming in Java
Java ee7 1hour
InterConnect 2016 Java EE 7 Overview (PEJ-5296)
Getting Started with Java EE 7
Java EE 7 Recipes for Concurrency - JavaOne 2014
Concurrency-5.pdf
Java EE 7 Platform: Boosting Productivity and Embracing HTML5 - Arun Gupta (R...
Java EE 7: Boosting Productivity and Embracing HTML5
S314168 - What's New in Enterprise Java Bean Technology @ JavaOne Brazil 2010
Boost Development With Java EE7 On EAP7 (Demitris Andreadis)
Don't Wait! Develop responsive applications with Java EE7 instead
Presente e Futuro: Java EE.next()
JavaOne 2007 - TS4721
AAI-1713 Introduction to Java EE 7
Ad

More from Haim Yadid (20)

PDF
On-Call AI Assistant: Streamlining Production Error Investigation with LLM
PDF
Loom me up Scotty! Project Loom - What's in it for Me?
PDF
“Show Me the Garbage!”, Garbage Collection a Friend or a Foe
PDF
Kotlin Backend Development 6 Yrs Recap. The Good, the Bad and the Ugly
PPTX
“Show Me the Garbage!”, Understanding Garbage Collection
PDF
Java Memory Structure
PDF
Basic JVM Troubleshooting With Jmx
PDF
The Freelancer Journey
PDF
Building microservices with Kotlin
PDF
Taking Kotlin to production, Seriously
PDF
Let's talk about Garbage Collection
PDF
JVM Garbage Collection logs, you do not want to ignore them! - Reversim Summi...
PDF
mjprof: Monadic approach for JVM profiling
PDF
Java 8 Launch - MetaSpaces
PDF
Java 8 - Stamped Lock
PDF
The Future of Futures - A Talk About Java 8 CompletableFutures
PDF
Concurrency and Multithreading Demistified - Reversim Summit 2014
PDF
A short Intro. to Java Mission Control
PDF
Tales About Scala Performance
PDF
Israeli JUG - IL JUG presentation
On-Call AI Assistant: Streamlining Production Error Investigation with LLM
Loom me up Scotty! Project Loom - What's in it for Me?
“Show Me the Garbage!”, Garbage Collection a Friend or a Foe
Kotlin Backend Development 6 Yrs Recap. The Good, the Bad and the Ugly
“Show Me the Garbage!”, Understanding Garbage Collection
Java Memory Structure
Basic JVM Troubleshooting With Jmx
The Freelancer Journey
Building microservices with Kotlin
Taking Kotlin to production, Seriously
Let's talk about Garbage Collection
JVM Garbage Collection logs, you do not want to ignore them! - Reversim Summi...
mjprof: Monadic approach for JVM profiling
Java 8 Launch - MetaSpaces
Java 8 - Stamped Lock
The Future of Futures - A Talk About Java 8 CompletableFutures
Concurrency and Multithreading Demistified - Reversim Summit 2014
A short Intro. to Java Mission Control
Tales About Scala Performance
Israeli JUG - IL JUG presentation

Recently uploaded (20)

PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Electronic commerce courselecture one. Pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Machine learning based COVID-19 study performance prediction
“AI and Expert System Decision Support & Business Intelligence Systems”
Mobile App Security Testing_ A Comprehensive Guide.pdf
Electronic commerce courselecture one. Pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
MIND Revenue Release Quarter 2 2025 Press Release
Empathic Computing: Creating Shared Understanding
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Review of recent advances in non-invasive hemoglobin estimation
Understanding_Digital_Forensics_Presentation.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Encapsulation_ Review paper, used for researhc scholars
Spectral efficient network and resource selection model in 5G networks
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
The AUB Centre for AI in Media Proposal.docx
Reach Out and Touch Someone: Haptics and Empathic Computing
Machine learning based COVID-19 study performance prediction

Java Enterprise Edition Concurrency Misconceptions

  • 1. JAVA EE CONCURRENCY MISCONCEPTIONS Haim Yadid, Performize-IT Ltd. Daniel Pfeifer, Whistler AB
  • 2. Daniel Pfeifer ‣ Founder of Performize-IT Ltd. ‣ 18+ years in technology ‣ Primary expertise in performance optimization ‣ Founder of Whistler AB ‣ 10+ years in IT ‣ Primary expertise in missioncritical business applications WHO ARE THOSE GUYS? Haim Yadid
  • 3. JAVA EE IN THE MULTIPROCESSOR ERA
  • 4. OPTIMISM Moore’s Law: The amount of transistors appx. doubles every second year
  • 5. JAVA EE IN THE FUTURE That’s why Multi core hardware will become mainstream for JEE servers
  • 7. A FRIENDLY ADVICE Don’t do it yourself !!
  • 8. There is an App Server for that
  • 9. TOOLS OF TRADE ‣ ”Local" and cluster-wide load balancing ‣ Message driven beans for parallelization / async tasks ‣ Asynchronous annotations ‣ Automatic and bean managed concurrency ‣ Resource management
  • 10. 6 REAL LIFE EXAMPLES
  • 12. You found yourself in need of sharing some data between calls so you ‣ Create a static constant pointing to a List (or perhaps your own singleton) ‣ Add a synchronization block for your constant ‣ You operate on your instance inside the synchronize-block SYNCHRONIZATION IN ENTERPRISE BEANS Use Case
  • 13. @Stateless public class SharedStateEJB { private static final List usedNumbers = new ArrayList(); public double fetchUnusedRandomNumber() { double number = 0d; synchronized (usedNumbers) { while (true) { number = Math.random(); if (!usedNumbers.contains(number)) { usedNumbers.add(number); break; } } } return number; } } SYNCHRONIZATION IN ENTERPRISE BEANS Returning unused random numbers
  • 14. Sharing state like this will not work, because … ‣ Static constants are not shared among class loaders ‣ A lock will not is not propagated across machines SYNCHRONIZATION IN ENTERPRISE BEANS Problems
  • 15. SYNCHRONIZATION IN ENTERPRISE BEANS What about Java EE Singleton?
  • 16. @Singleton public class UsedNumbersBean { private final List usedNumbers = new ArrayList(); @Lock(READ) public boolean numberExists(double num) { return usedNumbers.contains(num); } @Lock(WRITE) public void addNumber(double num) { usedNumbers.add(num); } } SYNCHRONIZATION IN ENTERPRISE BEANS @Singleton
  • 17. “Backup” solutions ‣ Use the database and use locking => Potentially slow ‣ Use a cluster-aware cache (i.e. EHCache or JBoss Cache) ‣  Read the chapters on clusters and consistency! ‣ Terracotta “Creative” solutions ‣ Use a single EJB ‣ Use H/A Singleton (available on JBoss) ‣ Wait for the future… SYNCHRONIZATION IN ENTERPRISE BEANS Suggestions
  • 19. •  You processed an order •  You ask the bank for settlement confirmation •  You can present the customer with a result without waiting for the bank ASYNCHRONICITY THROUGH THREADS Use Case
  • 20. @Stateless public class OrderHandlingBean { public String process(final Order order) { String orderId = ...//save order to database and get id final Thread t = new Thread() { @Override public void run() { // submit amount to bank } }; t.start(); // start “background” process return orderId; } } ASYNCHRONICITY THROUGH THREADS Creating a thread for async tasks
  • 21. ‣ Enough stuck Threads will eventually make your server go OOM. ‣ Difficult to get transaction management right. ‣  Some servers will tell you it can’t check the status, some don’t. ‣  Failed tasks in the thread need difficult manual rollback. ‣ Threads do not scale out ‣  Can’t be load-balanced to other machines. ‣  Server’s automatic resource management doesn’t cover your own threads. ‣ Debugging and monitoring isn’t the joy it used to be. ASYNCHRONICITY THROUGH THREADS Problems
  • 22. 1.8 1.6 Response Time 1.4 1.2 1 java.lang.OutOfMemoryError: unable to create new native thread Async 0.8 Sync 0.6 0.4 0.2 0 1h 4h 7h 10h 13h Runtime 16h 19h ASYNCHRONICITY THROUGH THREADS Thread bugs gone wild
  • 23. ‣ Until Java EE 6 Message Driven Beans are used for asynchronous tasks. ‣ And if you are lucky enough to use a Java EE 6 container, you can use the new @Asynchronous. ASYNCHRONICITY THROUGH THREADS Best Practice Alternatives
  • 24. @Stateless(name = ”QueueingEJB") public class QueueingBean { @Resource private Queue q; @Resource private ConnectionFactory cf; public String process(final Order order) { // ... saving the Order to the database and fetching id Connection cn = connectionFactory.createConnection(); Session s = cn.createSession(true, AUTO_ACKNOWLEDGE); MessageProducer producer = s.createProducer(queue); Message msg = s.createTextMessage(payment); producer.send(msg); return orderId; } } Don’t forget clean-up! We just want to conserve screen estate! ASYNCHRONICITY THROUGH THREADS Using Queues
  • 25. @MessageDriven(name = “PayEJB”, activationProperties = { /* activation properties for your server */ }) public class PayBean implements MessageListener { public void onMessage(Message m) { // Calling bank... } } ASYNCHRONICITY THROUGH THREADS Using Queues
  • 26. @Stateless(name = ”PayEJB") public class PayBean{ @Asynchronous public void callBank(final String payment) { // Hello, ... Bank! } } ASYNCHRONICITY THROUGH THREADS Using @Asynchronous
  • 27. @Stateless(name = ”AsyncCallerEJB") public class AsyncCallerBean { @EJB private PayBean payBean; public String process(final Order order) { // ... saving the Order to the database and fetching id payBean.callBank(payment); return orderId; // <- Returns + transaction OK } } That’s All!!! ASYNCHRONICITY THROUGH THREADS Using @Asynchronous
  • 28. We mentioned transactions… ‣ True, our examples won’t use the same Transaction, but… ‣  @Asynchronous will by spec create a Transaction (REQUIRES_NEW) ‣  MDBs will also create a transaction ASYNCHRONICITY THROUGH THREADS A note for the observant
  • 30. Your back-office staff fires off a bunch of invoices and you want the total as fast as possible, so you… ‣ Create a thread-pool ‣ Push all invoices for calculation to the thread-pool ‣ Wait for the answer and return it PARALLELISM WITH THREADPOOLS Use Case
  • 31. private static class OrderCallable implements Callable<Double> { private final Order order; public OrderCallable(Order order) { this.order = order; } @Override public Double call() throws Exception { // return the total based on the order that’s been // provided. } } PARALLELISM WITH THREADPOOLS Parallelizing with a ThreadPool (our Callable)
  • 32. public double processOrders(List<Order> orders) { ExecutorService executorService = Executors.newFixedThreadPool(10); List<Future<Double>> futures = new ArrayList<>(); for (Order order : orders) { OrderCallable callable = new OrderCallable (order); callables.add(callable); futures.add(executorService.invoke (callable)); } double totalValue = 0; try { for (Future<Double> future : futures) { totalValue += future.get(10, SECONDS); } } catch (TimeoutException e) { return -1; } return totalValue; } PARALLELISM WITH THREADPOOLS Parallelizing with a ThreadPool (using the Callable in an ExecutorService)
  • 33. Essentially we got the same problems as previously, but… ‣ Potential for much larger thread leaks ‣ Still not covered by transaction ‣ Executors, just like Threads, won’t run tasks on other machines. ‣ There is nothing H/A about this. ‣  On crash, part or all of the workload is gone. ‣  Can’t be resumed on server restart, it’s just gone… PARALLELISM WITH THREADPOOLS Problems
  • 34. ‣ Up to and including Java EE 5 you can use MDBs ‣  Queues can be clustered, so other servers can take some of the load. ‣ @Asynchronous-annotated method returning Future PARALLELISM WITH THREADPOOLS Pure Java EE alternatives
  • 35. Using @Asynchronous (invokee) @Stateless @Asynchronous public class ProcessBean { public Future<Double> getTotals(Order order) { double value = // .. Calculate value; return new AsyncResult<Double>(value); } }
  • 36. @Stateless public class OrderBean { @EJB private ProcessBean processBean; public double parallelizeCalculationAsync(List<Order> orders) { List<Future<Double>> futures = new ArrayList<>(); for (Order order : orders) { futures.add(processBean.getTotals(order)); } double totalValue = 0; try { for (Future<Double> future : futures) { totalValue += future.get(10, SECONDS); } } catch (Exception e) { // ignore } return totalValue; } } PARALLELISM WITH THREADPOOLS Using @Asynchronous (invoker)
  • 37. @Stateless public class OrderBean { @Resource(mappedName = “ConnectionFactory”) private ConnectionFactory cf; @Resource(mappedName = “RequestQ”) private Destination sendQueue; @Resource(mappedName = “ResponseQ”) private Destination responseQueue; @TransactionAttribute(NOT_SUPPORTED) // or UserTransaction public double handleOrders(List<Order> orders) { try { // …create a producer for (Order o : orders) { ObjectMessage outgoing = s.createObjectMessage(); outgoing.setObject(o); outgoing.setLongProperty(“RequestID”, orders.hashCode()) mp.send(outgoing); } cn.start(); // must be started, otherwise we can't receive MessageConsumer mc = s.createConsumer(responseQueue, "JMSCorrelationID = '" + orders.hashCode() + "'"); double totalValue = 0; for (int i = 0; i < orders.length(); i++) totalValue += mc.receive(10, SECONDS).getDoubleProperty(“OrderValue”); return totalValue; } catch (JMSException e) { throw new EJBException(e); } } } Send Receive PARALLELISM WITH THREADPOOLS Using MDB (invoker)
  • 38. @MessageDriven(mappedName = “RequestQ”) public class ProcessOrderBean implements MessageListener { @Resource(mappedName = “ConnectionFactory") private ConnectionFactory cf; @Resource(mappedName = “ResponseQ") private Queue responseQueue; public void onMessage(Message message) { double orderValue = // ... Process order try { MessageProducer mp = // … create message producer Message msg = s.createMessage(); msg.setJMSCorrelationID(message.getIntProperty(“RequestID”)); msg.setDoubleProperty(”OrderValue”, orderValue); mp.send(msg); } catch (JMSException e) { throw new EJBException(e); } } } PARALLELISM WITH THREADPOOLS Using MDB (invokee)
  • 39. PARALLELISM WITH THREADPOOLS A nice write up, but is it worth it?
  • 40. 12000 10000 8000 1 user 6000 10 users 20 users 4000 2000 0 Serial 8 parallel PARALLELISM WITH THREADPOOLS Response time – Compute intensive Tasks
  • 41. FORK AND KNIVES… UHM… JOIN
  • 42. ‣ New to Java 7 java.util.concurrent ‣ Helps you write a parallel recursive algorithm ‣ Break a long task to Fine grained tasks ‣ Very efficient for relatively short tasks FORK JOIN Introduction
  • 44. class PartialTask extends RecursiveAction { protected void compute() { PartialTask pt1 = new PartialTask(firstHalf); PartialTask pt2 = new PartialTask(secondHalf); pt1.fork(); // fork pt2.exec(); // execute in new thread pt1.join(); // wait for completion } } fjPool = new ForkJoinPool(para); Para.invoke(task) FORK JOIN Example
  • 45. ‣ Divide n points into k clusters ‣ Based on proximity FORK JOIN A Benchmark K-Means Clustering Algorithm
  • 46. ‣ This is not a formal benchmark ‣ I tried to do my best but it is not community criticized ‣ Ran on 8 core machine (no HT) ‣ Windows OS ‣ Warm-up was taken into account J ‣ 120K points to 50 clusters FORK JOIN Disclaimer
  • 47. FORK JOIN Response Time – by amount of parallelism 6000" 5000" Time%(sec)% 4000" 3000" Time" 2000" 1000" 0" 1" 2" 3" 4" 5" #cores%used% 6" 7" 8"
  • 48. FORK JOIN Speedup– by amount of parallelism 6" 5" Time%(sec)% 4" 3" Speedup" 2" 1" 0" 1" 2" 3" 4" 5" #cores%used% 6" 7" 8"
  • 49. FORK JOIN Single Operation Throughput Op/sec' 1" 0.8" 0.6" Op/sec" 0.4" 0.2" 0" 1" 2" 3" 4" 5" 6" 7" 8"
  • 50. ‣ Does your server need to do anything else ? ‣ Selfish Task Deplete all compute resources slows other task ‣ What about throughput FORK JOIN FJ on a JEE Server
  • 51. FORK JOIN What About Throughput ? Lets check !
  • 52. ‣ What will be better FORK JOIN Throughput of 8 Concurrent Users
  • 53. FORK JOIN Throughput 8 concurrent users in parallel Op/sec' 1.8" 1.6" 1.4" 1.2" 1" 0.8" 0.6" 0.4" 0.2" 0" Op/sec" Serial"Algorithm" Fork"Join" Parallelism"1" Fork"Join" Parallelism"8"
  • 55. ‣ Use FJ for the non common case ‣ Limit the number of cores do not starve other server tasks FORK JOIN Conclusion
  • 56. LOAD MANAGEMENT FOR BACKEND ACCESS
  • 57. You have a backend machine that can only handle 20 concurrent requests and you have a cluster of four servers, so you… ‣ Create a semaphore with five permits. ‣ Acquire lock on semaphore ‣ Call server ‣ Release lock LOAD MANAGEMENT FOR BACKEND ACCESS Use Case
  • 58. ‣ The backend server can be under-utilized across the cluster. ‣  First server could be full of locks while second is free. ‣ One server can stall unnecessarily long time. ‣ Recompile necessary if some parameter changes. LOAD MANAGEMENT FOR BACKEND ACCESS Problems With This Approach
  • 59. Using the Request-Reply Pattern (EIP), using: ‣ Clustered queues (request + response) ‣ A caller (stateless session bean) ‣ A backend invoker bean (message-driven bean) ‣ Configuration to limit in-process messages For the advanced: ‣ Write a resource adapter (JCA) ‣  Support load balancing ‣  Support cluster LOAD MANAGEMENT FOR BACKEND ACCESS A Better Approach
  • 60. @Stateless public class DispatcherBean { @Resource(mappedName = “ConnectionFactory”) private ConnectionFactory cf; @Resource(mappedName = “RequestQ”) private Destination sendQueue; @Resource(mappedName = “ResponseQ”) private Destination responseQueue; @TransactionAttribute(NOT_SUPPORTED) // Alternatively UserTransaction public double checkStockRate(String stockName) { try { //… create producer Message outgoing = s.createMessage(); outgoing.setStringProperty(”StockName", stockName); mp.send(outgoing); Send String correlationId = outgoing.getJMSMessageID(); cn.start(); // must be started, otherwise we can't receive MessageConsumer mc = s.createConsumer(responseQueue, "JMSCorrelationID = '" + correlationId + "'"); Message incoming = mc.receive(10000L); // wait no more than 10 seconds if (incoming != null) { return incoming.getDoubleProperty(”StockPrice"); } else { return Double.MIN_VALUE; } } catch (JMSException e) { throw new EJBException(e); } } } Receive LOAD MANAGEMENT FOR BACKEND ACCESS Request-Reply Pattern using clustered queues (Caller SLSB)
  • 61. @MessageDriven(mappedName = “RequestQ”) public class BackendInvokerBean implements MessageListener { @Resource(mappedName = “ConnectionFactory") private ConnectionFactory cf; @Resource(mappedName = “ResponseQ") private Queue responseQueue; public void onMessage(Message message) { double stockPrice = // ... Fetch from backend service try { // … create producer Message msg = s.createMessage(); msg.setJMSCorrelationID(message.getJMSMessageID()); msg.setDoubleProperty(”StockPrice”, stockPrice); mp.send(msg); } catch (JMSException e) { throw new EJBException(e); } } } LOAD MANAGEMENT FOR BACKEND ACCESS Request-Reply Pattern using clustered queues (Invoker MDB)
  • 62. Vendor-specific, but in general: ‣ You may set an upper limit on consumers ‣  Glassfish has maxNumActiveConsumers ‣ You may set an upper limit of MDBs in Pool ‣  Works on all servers regardless of vendor (i.e. set max-poolsize to 5 in glassfish-ejb-jar.xml) LOAD MANAGEMENT FOR BACKEND ACCESS Configuration for in-process limitation
  • 63. LOAD MANAGEMENT FOR BACKEND ACCESS Isn’t MDB horribly slow?
  • 64. 12 10 8 1 user 6 5 users 10 users 4 2 0 Direct MDB LOAD MANAGEMENT FOR BACKEND ACCESS Response time (in milliseconds)
  • 66. You occasionally suffer from resource depletion so to protect your server you: ‣ Create an EJB Interceptor that ‣  checks current beans in use (i.e. through counter or MBeans) ‣  throws an exception at chosen maximum size. ‣  Or wait until level go down ‣ Assign it to your EJB. INTERFERING WITH BEAN POOL Use Case
  • 67. ‣ Is there always equal load distribution across all tasks? ‣ Intelligent load balancers may continue to shoot at the wrong target ‣  It’s just an exception… not an overload ‣ DeadLock INTERFERING WITH BEAN POOL Problems
  • 68. Leave pool management to the server, pool sizes: ‣ Can be tuned on a global level ‣  Right strategy (infinite thread pools, incremental, fixed) ‣  Global default for min/max/timeout ‣ Can be set for each EJB ‣  XML ‣  Annotations (i.e. JBoss) INTERFERING WITH BEAN POOL Better approach
  • 69. It can be configured through the GUI…(Glassfish example) INTERFERING WITH BEAN POOL Leave Management to the app server
  • 72. CONCLUSION ‣ Most mistakes stem from misunderstanding the app server, try to understand your app server’s OOTB-capabilities… ‣ …and the Java EE specification. ‣ If you have a valid case for your own concurrency-related code, make sure it plays well with the container. ‣ Your app server doesn’t always know best, but it often does. And if not, you can often help it understand! ‣ Do not expect your environment to always look the same, it changes quicker than you might think.