74
JAVA EE CONCURRENCY MISCONCEPTIONS Haim Yadid, Performize-IT Ltd. Daniel Pfeifer, Whistler AB

Java Enterprise Edition Concurrency Misconceptions

Embed Size (px)

DESCRIPTION

A session given by Daniel Pfeifer and myself on JavaOne 2011

Citation preview

Page 1: Java Enterprise Edition Concurrency Misconceptions

JAVA EE CONCURRENCY MISCONCEPTIONS Haim Yadid, Performize-IT Ltd. Daniel Pfeifer, Whistler AB

Page 2: Java Enterprise Edition Concurrency Misconceptions

WH

O AR

E THO

SE G

UY

S? Haim Yadid

‣ Founder of Performize-IT Ltd. ‣ 18+ years in

technology ‣ Primary expertise in

performance optimization

Daniel Pfeifer ‣ Founder of

Whistler AB ‣ 10+ years in IT ‣ Primary expertise in mission-

critical business applications

Page 3: Java Enterprise Edition Concurrency Misconceptions

JAVA EE IN THE MULTIPROCESSOR ERA

Page 4: Java Enterprise Edition Concurrency Misconceptions

OP

TIMIS

M

Moore’s Law: The amount of transistors appx. doubles every second year

Page 5: Java Enterprise Edition Concurrency Misconceptions

JAV

A EE

IN THE FU

TUR

E

That’s why Multi core hardware will become mainstream for JEE servers

Page 6: Java Enterprise Edition Concurrency Misconceptions

IS MU

LTICO

RE N

EW

TO JAV

A EE

? Budget machines

0"

2"

4"

6"

8"

10"

12"

14"

16"

18"

2006" 2008" 2010" 2012"

CPUs/server"CPUs/phone"CPUs/notebook"

Page 7: Java Enterprise Edition Concurrency Misconceptions

A FR

IEN

DLY A

DV

ICE Don’t do it yourself !!

Page 8: Java Enterprise Edition Concurrency Misconceptions

There is an App for that Server

Page 9: Java Enterprise Edition Concurrency Misconceptions

TO

OLS O

F TRA

DE

‣  ”Local" and cluster-wide load balancing ‣ Message driven beans for parallelization / async tasks ‣ Asynchronous annotations ‣ Automatic and bean managed concurrency ‣ Resource management

Page 10: Java Enterprise Edition Concurrency Misconceptions

6 REAL LIFE EXAMPLES

Page 11: Java Enterprise Edition Concurrency Misconceptions

SYNCHRONIZATION IN EJB

Page 12: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

Use Case 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

Page 13: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

Returning unused random numbers @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; } }

Page 14: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

Problems

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

Page 15: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

What about Java EE Singleton?

Page 16: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

@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);

}

}

Page 17: Java Enterprise Edition Concurrency Misconceptions

SY

NC

HR

ON

IZATIO

N IN EN

TER

PR

ISE B

EA

NS

Suggestions “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…

Page 18: Java Enterprise Edition Concurrency Misconceptions

ASYNCHRONICITY THROUGH THREADS

Page 19: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Use Case •  You processed an order •  You ask the bank for settlement confirmation •  You can present the customer with a result without waiting for the

bank

Page 20: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Creating a thread for async tasks @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;

}

}

Page 21: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Problems

‣ 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.

Page 22: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Thread bugs gone wild

0

0.2

0.4

0.6

0.8

1

1.2

1.4

1.6

1.8

1h 4h 7h 10h 13h 16h 19h

Res

pons

e Ti

me

Runtime

Async Sync

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

Page 23: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Best Practice Alternatives

‣ 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.

Page 24: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Using Queues @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!

Page 25: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Using Queues

@MessageDriven(name = “PayEJB”, activationProperties = { /* activation properties for your server */

})

public class PayBean implements MessageListener { public void onMessage(Message m) { // Calling bank...

}

}

Page 26: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

Using @Asynchronous @Stateless(name = ”PayEJB") public class PayBean{

@Asynchronous public void callBank(final String payment) {

// Hello, ... Bank!

}

}

Page 27: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

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!!!

Page 28: Java Enterprise Edition Concurrency Misconceptions

AS

YN

CH

RO

NIC

ITY THR

OU

GH T

HR

EA

DS

A note for the observant 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

Page 29: Java Enterprise Edition Concurrency Misconceptions

PARALLELISM WITH THREAD POOLS

Page 30: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Use Case 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

Page 31: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Parallelizing with a ThreadPool (our Callable)

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.

}

}

Page 32: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Parallelizing with a ThreadPool (using the Callable in an ExecutorService) 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; }

Page 33: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Problems

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…

Page 34: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Pure Java EE alternatives

‣ 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

Page 35: Java Enterprise Edition Concurrency Misconceptions

Using @Asynchronous (invokee) @Stateless @Asynchronous public class ProcessBean {

public Future<Double> getTotals(Order order) {

double value = // .. Calculate value;

return new AsyncResult<Double>(value);

}

}

Page 36: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Using @Asynchronous (invoker) @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; } }

Page 37: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Using MDB (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

Page 38: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Using MDB (invokee) @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); } } }

Page 39: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

A nice write up, but is it worth it?

Page 40: Java Enterprise Edition Concurrency Misconceptions

PA

RA

LLELIS

M W

ITH TH

RE

AD

PO

OLS

Response time – Compute intensive Tasks

0

2000

4000

6000

8000

10000

12000

Serial 8 parallel

1 user 10 users 20 users

Page 41: Java Enterprise Edition Concurrency Misconceptions

FORK AND KNIVES… UHM… JOIN

Page 42: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Introduction

‣ 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

Page 43: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Introduction

Worker

Worker

Worker

Worker

ForkJoinTask ForkJoinPool

Page 44: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Example

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)

Page 45: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN A Benchmark K-Means Clustering Algorithm ‣ Divide n points into k clusters ‣ Based on proximity

Page 46: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Disclaimer

‣ 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

Page 47: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Response Time – by amount of parallelism

0"

1000"

2000"

3000"

4000"

5000"

6000"

1" 2" 3" 4" 5" 6" 7" 8"

Tim

e%(sec)%

#cores%used%

Time"

Page 48: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Speedup– by amount of parallelism

0"

1"

2"

3"

4"

5"

6"

1" 2" 3" 4" 5" 6" 7" 8"

Tim

e%(sec)%

#cores%used%

Speedup"

Page 49: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Single Operation Throughput

0"

0.2"

0.4"

0.6"

0.8"

1"

1" 2" 3" 4" 5" 6" 7" 8"

Op/sec'

Op/sec"

Page 50: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN FJ on a JEE Server

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

Page 51: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN

What About Throughput ?

Lets check !

Page 52: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Throughput of 8 Concurrent Users ‣ What will be better

Page 53: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Throughput 8 concurrent users in parallel

0"0.2"0.4"0.6"0.8"1"

1.2"1.4"1.6"1.8"

Serial"Algorithm" Fork"Join"Parallelism"1"

Fork"Join"Parallelism"8"

Op/sec'

Op/sec"

Page 54: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Response Time

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

Serial"Algorithm"

Fork"Join"Parallelism"1"

Fork"Join"Parallelism"8"

TRT"of"8"Users"

TRT"of"1"User"

Page 55: Java Enterprise Edition Concurrency Misconceptions

FO

RK JO

IN Conclusion

‣ Use FJ for the non common case ‣ Limit the number of cores do not starve other server tasks

Page 56: Java Enterprise Edition Concurrency Misconceptions

LOAD MANAGEMENT FOR BACKEND ACCESS

Page 57: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Use Case 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

Page 58: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Problems With This Approach ‣ 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.

Page 59: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S A Better 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

Page 60: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Request-Reply Pattern using clustered queues (Caller SLSB)

@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); 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); } } }

Send

Receive

Page 61: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Request-Reply Pattern using clustered queues (Invoker MDB) @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); } } }

Page 62: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Configuration for in-process limitation 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-pool-size to 5 in glassfish-ejb-jar.xml)

Page 63: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S

Isn’t MDB horribly slow?

Page 64: Java Enterprise Edition Concurrency Misconceptions

LO

AD M

AN

AG

EM

EN

T FOR B

AC

KE

ND A

CC

ES

S Response time (in milliseconds)

0

2

4

6

8

10

12

Direct MDB

1 user 5 users 10 users

Page 65: Java Enterprise Edition Concurrency Misconceptions

INTERFERING WITH BEAN POOL

Page 66: Java Enterprise Edition Concurrency Misconceptions

INTE

RFE

RIN

G WITH B

EA

N PO

OL

Use Case

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.

Page 67: Java Enterprise Edition Concurrency Misconceptions

INTE

RFE

RIN

G WITH B

EA

N PO

OL

Problems

‣  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

Page 68: Java Enterprise Edition Concurrency Misconceptions

INTE

RFE

RIN

G WITH B

EA

N PO

OL

Better approach 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)

Page 69: Java Enterprise Edition Concurrency Misconceptions

INTE

RFE

RIN

G WITH B

EA

N PO

OL

Leave Management to the app server It can be configured through the GUI…(Glassfish example)

Page 70: Java Enterprise Edition Concurrency Misconceptions

INTE

RFE

RIN

G WITH B

EA

N PO

OL

Through Config Files <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>

Page 71: Java Enterprise Edition Concurrency Misconceptions

CONCLUSION

Page 72: Java Enterprise Edition Concurrency Misconceptions

CO

NC

LUS

ION

‣ 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.

Page 73: Java Enterprise Edition Concurrency Misconceptions

QUESTIONS?

Page 74: Java Enterprise Edition Concurrency Misconceptions

CO

NTA

CT IN

FO Haim Yadid [email protected]

Daniel Pfeifer [email protected]