SlideShare a Scribd company logo
1 of 95
Phillip Koza
IBM
Maximizing Throughput and
Reliability with Pipelined Tasks
JavaOneJavaOne
JavaOneJavaOne
2
Agenda
What is pipelining?
When to pipeline
Creating/starting stages and threads
Stage/thread communication
Waiting/flushing
Stopping stages/threads
Uncaught exception handling
Shutdown hooks, Daemon threads
Summary
JavaOneJavaOne
3
What is pipelining?
JavaOneJavaOne
4
JavaOneJavaOne
5
What is pipelining?
Pipelining is processing a given job as a series of
cooperating, dependent, sequential stages
Each stage does a subset of the processing, then hands off
to the next stage
Each stage is a separate thread or threads
Each stage has at least one input queue and at least one
output queue
These queues may be logical
Don’t want a stage to get too far ahead of its successor
Stages should block if they are too far ahead
JavaOneJavaOne
6
What is pipelining?
Well understood and utilized concept in microprocessors:
almost all processor chips are heavily pipelined
 Pipelining is operator-based parallelism, as opposed to data
(partition-based) parallelism
 Each stage executes in parallel a subset of the operations
that need to be performed on all objects/tasks
 Partition based parallelism executes in parallel all
operations on a subset of the objects/tasks
Both forms of parallelism can be utilized at once!
JavaOneJavaOne
7
Example – Stock data app
StoreStore
ParseParse
Read allRead all
stockstock
datadata
TechnologyTechnology
stockstock
data subscriberdata subscriber
CommodityCommodity
stockstock
data subscriberdata subscriber
Financial stockFinancial stock
data subscriberdata subscriber
JavaOneJavaOne
8
Why pipelining?
Increased throughput , responsiveness, and processor
utilization
If n stages, a well balanced pipeline can increase cpu
utilization and throughput by a factor of close to n
Other stages can continue processing if a stage must perform
I/O
Flexibility: easy to add additional processing – just add
another stage!
Maintainability: code follows the pipeline – harder to have
monolithic 3000 line methods that do everything!
JavaOneJavaOne
9
Pipeline topologies
Basic: Single producer to single consumer
Pipelining + partitioned input processing: multiple
producers to single consumer
Each producer processes a partition of the input
Pipelining + partitioned output processing: single producer
to multiple consumers
Each consumer processes a partition of the output
Multiple producers + multiple consumers
Complicated: if possible, have separate pipelines!
JavaOneJavaOne
10
When to pipeline
Complex job with multiple processing modules
Stage candidates: when should you consider having a
module run as a separate stage?
Running in a separate thread is not free: must consider
additional startup, synchronization, complexity
The benefits must be weighed against these additional costs
Luckily, there are ways to minimize these costs!
A key to effective pipelining is determining which modules
to run as pipeline stages
JavaOneJavaOne
11
When to pipeline
Module does I/O
Module does significant processing that is not interleaved
with that of other stages
Profiling shows this module is a bottleneck
JavaOneJavaOne
12
When to pipeline
Ideally, all stages are perfectly balanced: if n stages, each
stage does 1/n of the work
Each stage then never waits for input (except at startup) and
never waits to deliver output
If not perfectly balanced, some stages may get ahead of the
others
These stages should block until the other stages catch up
Number of stages is usually statically fixed when the
pipeline starts
JavaOneJavaOne
13
Partition parallelism
 Partition parallelism is having separate threads process a portion
(partition) of the data stream
 The partitions are not necessarily disjoint
 Can be utilized whenever objects can be processed in any order,
OR you know how to merge them into the correct order
 Can be used to increase overall throughput, or throughput of
individual stages
 If objects can be processed in any order, can have an independent
pipeline for each partition
 Overhead may be too high if some stages are very lightweight
 If dependencies, must merge the streams at some point – so need a
common pipeline
 Partition threads can be allocated statically or dynamically
JavaOneJavaOne
14
How many threads?
Keep track of how often consumers wait for producers and
vice-versa
Lots of consumer waits = more producer threads
Lots of producer waits = more consumer threads
This can mean adding more pipelines, more pipeline stages,
or more threads per stage
Adding more threads to slow stages is particularly useful for
balancing stages
JavaOneJavaOne
15
When to pipeline
Example: Determine stage boundaries
To compile a SQL query, the SQL compiler must:
Lexically analyze the query
Parse the token stream from the lexer
Bind objects (table, column, etc)
Normalize
Optimize
Generate query plan
Currently one thread is doing all of the above processing
JavaOneJavaOne
16
When to pipeline
Example: Determine stage boundaries
Analysis shows that:
Lexer, Parser and Binder use significant CPU and can do I/O
(catalog table lookups)
 But calls to these modules can be interleaved, so should not be split
 Binding a view will require the underlying query expression to be lexically
analyzed and parsed
Normalizer, optimizer, and code generator all use significant
CPU and these calls are not interleaved
JavaOneJavaOne
17
When to pipeline
Example: Determine stage boundaries
Split into the following stages:
Lexer/Parser/Binder
Normalizer
Optimizer
Code generator
 Each stage can then execute in parallel
Normalization, optimization, and code generation can continue
if the Binder must do I/O
Each stage of processing proceeds in parallel
JavaOneJavaOne
18
Creating threads
ExecutorService or raw threads?
JavaOneJavaOne
19
Creating threads
ThreadPoolExecutor
Implements ExecutorService
Best when have lots of independent short running tasks that
terminate themselves
Provides automatic thread reuse via pooling
Pooling pays off big for short running tasks
JavaOneJavaOne
20
Creating threads
ThreadPoolExecutor
Creates threads via ThreadFactory
Default is Executors.defaultThreadFactory
Can create your own and set via setThreadFactory
Can specify own thread name, priority, group, etc
JavaOneJavaOne
21
Creating threads
 ThreadPoolExecutor
 In a pipeline, this can be useful for creating additional threads for
partitioned parallelism for a pipeline stage
 Each stage has its own ThreadPoolExecutor
 Threads can be added as the stage load increases, returned to the
pool when the stage load decreases
 Control maximum number of idle threads and total threads by
setting corePoolSize and maximumPoolSize
 It’s important to limit the maximumPoolSize
 Unlimited growth in the number of threads can quickly exhaust all
resources
JavaOneJavaOne
22
Creating threads
ThreadPoolExecutor
Unless an unlimited maximumPoolSize is specified, a
request for another thread will block waiting for a thread to
become available
If no more threads immediately available, would rather just
use one of the existing threads
So use a SynchronousQueue as the work queue
Using the default RejectedExecutionHandler, the request will
be rejected if the maximum number of threads are already in
use
 i.e. a RejectedExecutionException will be thrown
JavaOneJavaOne
23
Using ThreadPoolExecutor
private static final maxThreads = 5;
private SynchronousQueue syncQ = new SynchronousQueue();
private ExecutorService threadPool = new ThreadPoolExecutor(maxThreads,
maxThreads, 60, TimeUnit.SECONDS,syncQ);
public boolean addWorkerThread(StageWorker worker) {
try {
threadPool.execute(new StageRunnable(worker));
}
catch (RejectedExecutionException) {
return false;
}
return true;
}
JavaOneJavaOne
24
Creating threads
Raw threads
Gives maximum control over when threads are created,
started, and stopped
The best choice when you have long running dependent
tasks, i.e. a pipeline
Pipelines need maximum control over their threads
All stage threads should be up, or all should be down
Need precise control over the timing of starting and stopping
threads
JavaOneJavaOne
25
Creating threads
 Pooling potentially useful, but not as important
 Thread creation is not the dominant cost
 Be very careful if have one giant thread pool for all stages and
pipelines!
 A pipeline does not function unless all stages are executing
 Don’t want some pipeline stages to be queued awaiting execution
while others are running
 If need to limit the total number of threads, it is best to limit the number
of pipelines
 For a pipeline, raw threads are the best choice – for now, at least!
JavaOneJavaOne
26
Using raw threads
private static final maxThreads = 5;
private threadCount = 0;
private final List<Thread> threadList = new ArrayList<Thread>(maxThreads);
public boolean addWorkerThread(StageWorker worker) {
if (threadCount < maxThreads) {
Thread stageThread = new Thread(new StageRunnable(worker));
threadList.add(stageThread);
threadCount++;
stageThread.start();
return true;
}
return false;
}
JavaOneJavaOne
27
Starting threads
Two basic control models:
MVC (Model/View/Controller)
Waterfall (hierarchical)
JavaOneJavaOne
28
Starting threads - MVC
Model is the data flow
View is presentation of the monitoring data/return data
Controller logic is kept separate
Dedicated controller thread
Controller must be aware of all stages/threads, how to start
them, and how they are linked
Controller can precisely control which threads get created
first
JavaOneJavaOne
29
Starting threads - MVC
Controller starts all stages/threads when the pipeline starts
Messages/callbacks to the controller are used to restart or
add additional stages/threads
Controller must ensure predecessor and successor stages
properly handle this
Controller can monitor pipeline state
If a stage thread dies unexpectedly, can restart the stage
But safest and easiest thing to do is to bring down the entire
pipeline
JavaOneJavaOne
30
MVC Diagram
Stage 3Stage 3
Sink
Source
ControllerController
Stage 2Stage 2
Stage 1Stage 1
JavaOneJavaOne
31
Starting threads - Waterfall
No dedicated control thread
Start from the head of the pipeline, i.e. the final consumer
stage/thread
Each successor (parent) stage creates any immediate
predecessor (child) stage threads that it needs
Control “falls” from parent to child, hence the name
If any child stage/thread dies, parent must notice and handle
(restart child, stop itself, etc)
JavaOneJavaOne
32
Starting threads - Waterfall
In effect, each parent thread acts as the controller for the
child
If additional child threads for a stage are needed, the parent
creates them
 Siblings should not create additional siblings – only a parent should!
(the parent may be quite happy with the number of children it
already has!)
JavaOneJavaOne
33
Waterfall Diagram
Stage 3Stage 3
Sink
Source
Stage 2Stage 2
Stage 1Stage 1
ChildChild
ParentParent
ChildChild
ParentParent
createscreates
createscreates
JavaOneJavaOne
34
Starting threads
MVC advantages
Components do not need to know who their predecessors or
successors are
All pipeline control logic is in one place
 Easy to refactor code to add/remove stages
 Makes maintenance easier
MVC disadvantages
Must be careful to avoid starting a predecessor stage before
the successor is ready
JavaOneJavaOne
35
Starting threads
Waterfall advantages
Parent has complete control of its child
 Can start and stop child threads as it pleases
Parent can easily guarantee that the child is not started until
the parent is ready
Waterfall disadvantages
Logic to start/stop stages is in each successor stage
 Harder to add/remove stages
 Each stage has its predecessor hard-coded
 Logic can become subtly different over time
 Separate logic harder to find, maintain
JavaOneJavaOne
36
Stage/thread communication
 How do you move data from one stage to the next?
 Single producer to single consumer
 Producer adds data to [logical] output queue, consumer reads
 Multiple producers to single consumer
 Each producer adds data to its [logical] output queue, consumer reads
from each producer queue, merging output if necessary
 Single producer to multiple consumers, consumers process any
available data
 Producer adds data to a single [logical] output queue, each consumer
reads next available
JavaOneJavaOne
37
Stage/thread communication
 Single producer to multiple consumers, consumers process a
partition of the data
 Each consumer requires a not necessarily distinct subset of the data
 Two potential models: push vs. pull
 Push: producer determines what data to give to each consumer,
and then sends it to each
 Producer has to know what the consumer wants
 Producer must allocate time to do this
 Producer may have data to give, but consumer is not ready
 Consumer may be ready for data, and the producer may have data to
give, but the producer is busy doing other things
JavaOneJavaOne
38
Stage/thread communication
Pull: Consumer gets the data it needs directly from the
producer
Producer doesn’t need to spend time determining what data a
consumer needs and sending it
If data is available, consumer doesn’t have to wait for the
producer to send it
 Requires consumer to access producer data structures –
which means synchronization!
Pull has the potential to perform better, but is more
complicated
JavaOneJavaOne
39
Push Example – Stock data app
Store,Store,
DistributeDistribute
ParseParse
Read allRead all
stockstock
datadata
queuequeue
queuequeue
queuequeue
TechnologyTechnology
stockstock
data subscriberdata subscriber
CommodityCommodity
stockstock
data subscriberdata subscriber
Financial stockFinancial stock
data subscriberdata subscriber
JavaOneJavaOne
40
Pull Example – Stock data app
StoreStoreParseParse
Read allRead all
stockstock
datadata
SynchSynch
AccessAccess
to storeto store
SynchSynch
AccessAccess
to storeto store
SynchSynch
AccessAccess
to storeto store
TechnologyTechnology
stockstock
data subscriberdata subscriber
Financial stockFinancial stock
data subscriberdata subscriber
CommodityCommodity
stockstock
data subscriberdata subscriber
JavaOneJavaOne
41
Stage/thread communication
Pipes
Synchronized structures + wait/notify
Blocking queues
JavaOneJavaOne
42
Stage/thread communication
 PipedOutputStream, PipedInputStream
 Advantages:
 Can layer the wide variety of stream classes to do transforms, etc.
 Synchronization, waiting, notification is handled for you
 A full output pipe automatically forces a producer that is too fast to slow down
 Buffer size expressed in bytes – great if you want to strictly control the memory
used
 Disadvantages
 All objects must be serialized – not so great if you are not ultimately writing to
disk
 Must be 1:1 – one producer and one consumer (per pipe)
 Push only
JavaOneJavaOne
43
Producer w/ Pipes
public class Stage1 implements StageWorker{
private PipedOutputStream outPipe;
Stage1(Stage successor) {
outPipe = new PipedOutputStream(successor.inPipe);
}
…
private void sendData(WorkUnit workUnit) {
ObjectOutputStream outObjStream = new ObjectOutputStream(outPipe);
workUnit.writeObject(outObjStream);
}
}
JavaOneJavaOne
44
Consumer w/ Pipes
public class Stage2 implements StageWorker {
public PipedInputStream inPipe;
Stage2() {
inPipe = new PipedInputStream();
}
…
private WorkUnit receiveData() {
ObjectInputStream inObjStream = new ObjectInputStream(inPipe);
WorkUnit workUnit = new WorkUnit();
workUnit.readObject(inObjStream);
return workUnit;
}
}
JavaOneJavaOne
45
Stage/thread communication
 Synchronized structures + wait/notify
 Advantages:
 Allows multiple consumers to access upstream data at their own pace,
i.e. they can pull their data instead of having it pushed to them
 Consumers determine what data they want
 Disadvantages:
 Producers and consumers must synchronize on the same object
 Must manage synchronization, waiting, notification yourself
 This includes making the producer wait if consumers are falling behind
 Cannot read while writing and vice-versa
JavaOneJavaOne
46
Producer w/ Synchronized Access
public class Stage1 implements StageWorker {
public LinkedList<WorkUnit> outList ;
Stage1(Stage successor) {
outList = new LinkedList<WorkUnit>(1000);
}
…
private void sendData(WorkUnit workUnit) {
synchronized(outList) {
outList.add(workUnit);
outList.notifyAll();
}
}
JavaOneJavaOne
47
Consumer w/ Synchronized Access
public class Stage2 implements StageWorker {
private ArrayList<WorkUnit> inList;
public int currentPos = 0; // This needs to be adjusted for removals
Stage2(Stage predecessor) {
inputList = predecessor.outList;
}
…
JavaOneJavaOne
48
Consumer w/ Synchronized Access
private WorkUnit receiveData() {
WorkUnit workUnit = null;
synchronized(inList) {
while (currentPos >= inList.size()) {
try {
inList.wait(1000);
} catch (InterruptedException ie) {}
}
workUnit = inList.get(currentPos++);
}
return workUnit;
}
}
JavaOneJavaOne
49
Stage/thread communication
 ArrayBlockingQueue, LinkedBlockingQueue
 Use the capacity setting to control how far ahead a producer can get before it
blocks
 Advantages:
 Synchronization, waiting, notification is handled for you
 A full output queue automatically forces a producer that is too fast to slow down
 Can read while writing and vice-versa
 Capacity is expressed as a # of objects – great if you want to limit how many
objects the producer gets ahead of the consumer
 Disadvantages:
 Memory use can vary if object sizes are highly variable
 There is still a synchronization cost to put/take
 Push only
JavaOneJavaOne
50
Producer w/ ArrayBlockingQueue
public class Stage1 implements StageWorker {
private ArrayBlockingQueue outQueue ;
Stage1(Stage successor) {
outQueue = successor.inQueue;
}
…
private void sendData(WorkUnit workUnit) {
outQueue.put(workUnit);
}
}
JavaOneJavaOne
51
Consumer w/ ArrayBlockingQueue
public class Stage2 implements StageWorker {
public ArrayBlockingQueue<WorkUnit> inQueue;
Stage2() {
inQueue = new ArrayBlockingQueue<WorkUnit>;
}
…
private WorkUnit receiveData() {
WorkUnit workUnit = inQueue.take();
return workUnit;
}
}
JavaOneJavaOne
52
Stage/thread communication
Recommendations
 Use ArrayBlockingQueue except where there are multiple
consumers
LinkedBlockingQueue is not recommended, as it is unbounded
by default, and has higher memory utilization
If multiple consumers, have the consumers pull their data
using synchronization + wait/notify
JavaOneJavaOne
53
Stage/thread communication
 For good performance, it is critical to minimize the
synchronization costs of inter-stage communication
The key is maximizing the unit of work passed between
stages, i.e. buffering
 Batch up smaller units of work into buffers of larger ones
The buffers are passed between stages instead of the original
units of work
Buffering can decrease responsiveness
The key here is to flush the buffers whenever any thread must
wait
JavaOneJavaOne
54
Stage/thread communication
When using ArrayBlockingQueue:
Wrap in a custom queue that buffers objects and puts the
buffers to the underlying queue, instead of the actual objects
Take from the queue then gets the buffers, and processes
them
When using synchronized access:
Producer buffers objects, then adds full buffers to the
synchronized common data structure
Consumers read full buffers from the synchronized common
data structure
JavaOneJavaOne
55
Waiting/Flushing
Waiting indefinitely is dangerous!
Try to NEVER wait on anything indefinitely
If you are waiting for another thread to do something, and it
dies, you will be waiting forever
So, use loops+timeouts whenever possible
 When wake up, check if anyone wants you to stop, process a more
urgent request, etc.
 If not, re-issue request
JavaOneJavaOne
56
Waiting/Flushing
Interrupting threads
Dangerous to rely on interrupts to break indefinite waits
Who will send the interrupt and how will they know it’s needed?
 Interrupting thread must have a handle to the interrupted thread
JavaOneJavaOne
57
Waiting/Flushing
Interrupting threads
Could interrupt an I/O in process. The results of this are
unpredictable:
 InterruptedIOException
 I/O could have partially completed
 ClosedByInterruptException (if I/O was through a channel)
 Ignored
 For example, if thread is blocked waiting on a socket
(ServerSocket.accept)
Even if your module handles interrupts correctly – can you be
sure all called modules do?
Best to avoid using interrupts!
JavaOneJavaOne
58
Waiting/Flushing
Flush all buffers before waiting
Otherwise already processed data can get “stuck” in the
pipeline
Optimization: First wait with a short timeout, and then if still no
data, flush at that point
JavaOneJavaOne
59
Stopping
Requesting stop via thread interruption
If thread is interrupted, it assumes it should stop
 This is how ExecutorService.shutdownNow() and Future.cancel()
signal threads to stop
 So threads that stop this way will be stoppable if run as part of an
ExecutorService
 BUT:
JavaOneJavaOne
60
Stopping
Requesting stop via thread interruption
Class has to run as a thread, and it needs to know it is running
as a thread
 If thread is sleeping or waiting, InterrruptException will be thrown
which will clear the interrupted state
 The catch of InterruptedException has to signal the class to stop or has to
re-interrupt the thread
 Has all the problems mentioned earlier if an I/O is interrupted
 No granularity in the stop request
 Cannot distinguish between stop immediately and stop gracefully
So this is not recommended!
JavaOneJavaOne
61
Stopping
Requesting stop via flag objects
Have a stop request object that indicates thread should stop
Classes check regularly, and always before sleeping, waiting,
I/O, putting/getting from a blocking queue, etc.
Works the same regardless of whether the class is running as
a thread or not
Stop request object can indicate different types of stop: stop
immediate, stop gracefully (finish work in progress), etc.
 Stopping gracefully is important in a pipeline – in most cases, you
don’t want to lose the work already completed!
JavaOneJavaOne
62
Stopping
Have a stop request object that indicates thread should stop
Can have a single stop request object for the entire pipeline
that all threads monitor
 But this only allows the entire pipeline to be stopped
For finer granularity of stop control, have a pipeline stop
request object with references to stage/thread stop request
objects
Setting of stop request object must be synchronized – but this
does not occur very often
JavaOneJavaOne
63
Stopping
Have a request stop object that indicates thread should stop
Reading of the stop request object will occur frequently
Reading stop request object does not need to be synchronized
for most pipeline applications
 It is not critical to see a stop request instantaneously, and
synchronization doesn’t guarantee this anyway
 The stop request is typically a boolean or enum, so updates of it are
atomic
 There will be enough other synchronization boundaries crossed to
guarantee the stop request object modification will be seen
 Puts/gets to blocking queues, synchronized access to other shared
structures, etc.
 Synchronizing on write but not on read is known as Asymmetrical Locking
JavaOneJavaOne
64
Stopping
Detecting a stage/thread has actually stopped
Could use Thread.isAlive() to detect if a thread has
stopped
This requires a handle to the thread
Presumes the class is running as a thread
Won’t work for higher abstractions, such as a stage or
pipeline
JavaOneJavaOne
65
Stopping
Detecting a stage/thread has actually stopped
Better to make this abstract
Separate Runnable class from class that does the real work
Runnable class invokes the work class
The Runnable class has an “isRunning” object that tracks the
run status
All threads use this common Runnable class
Guarantees all threads have a common mechanism for
tracking run status
Can also be used to guarantee common handling for uncaught
exceptions
JavaOneJavaOne
66
Stopping
Detecting a stage/thread has actually stopped
The status of a stage is the logical-AND of the status
of the individual threads of that stage
The status of a pipeline is the logical-AND of the
status of the stages
If a graceful stop is requested, stages must wait for
their predecessor stages to actually stop before they
can stop
This allows in-flight data to be processed
JavaOneJavaOne
67
Stopping
Unexpected thread termination
Just set the stop request object to bring down all related
threads
Easiest and safest thing to do is bring down entire pipeline
JavaOneJavaOne
68
Stopping
Returning control to the user
Controller or highest level pipeline thread must make sure all
threads are truly stopped before returning
Strange things can happen if you try to start a pipeline and
some threads from its previous incarnation are still running!
Could call thread.join()
 But must have handle to all threads, and can’t be responsive to
other requests
Better for the controller to query the isRunning flag of all thread
classes and wait for all to be stopped.
JavaOneJavaOne
69
Example: buffering, flushing, stopping
work()
{
while (!checkForStopRequests()) {
int outBufSize = 100;
ArrayList<WorkUnit> outBuf = new ArrayList<WorkUnit>(bufSize);
ArrayList<WorkUnit> inBuf = inQueue.poll(1000,TimeUnit.MILLISECONDS);
// If have to wait for input, flush output
if (inBuf == null) {
if (outBuf.size() > 0) {
flushOutput();
}
}
JavaOneJavaOne
70
Example: buffering, flushing, stopping
else {
for (WorkUnit workUnit : inBuf) {
// process workUnit
…
outBuf.add(workUnit);
if (outBuf.size() > outBufSize) {
flushOutput();
}
}
}
}
JavaOneJavaOne
71
Example: buffering, flushing, stopping
flushOutput() {
boolean success = false;
while (!success && !checkForStopRequests()) {
success = outQueue.offer(outBuf,1000,TimeUnit.MILLISECONDS);
}
}
Boolean checkForStopRequests() {
// check for stop requests. Basic handling is:
if (stop requested) {
stageRunnableObj.isRunning = false;
return true; // stop this stage
}
return false;
}
JavaOneJavaOne
72
Uncaught exception handling
 Proper handling for uncaught exceptions is absolutely critical for a
pipeline!
 Uncaught exceptions are typically the leading cause of unexpected
thread termination
 Since all threads are dependent on others, if one goes down, the
entire pipeline can hang!
 A hung pipeline can be hard to detect
 Is it hung, or just in-between bursts of traffic?
 Proper monitoring statistics can help detect a hung pipeline
 It can take a while before you can be sure
 Auto-aborting a pipeline that is perceived to be hung will inevitably abort too soon in
certain situations
 So typically requires human intervention
 The best way to handle a hung pipeline is to prevent it!
JavaOneJavaOne
73
Uncaught exception handling
By default, uncaught exceptions are handled by the default
uncaught exception handler
This just writes the stack trace to standard error
This is rarely acceptable!
 Stack trace may be lost
 If class tracks its run status, this will be inaccurate after an uncaught
exception: run status will still be ‘running’
 What about threads that are dependent on this thread?
Don’t let the default happen to you!
JavaOneJavaOne
74
Uncaught exception handling
 Ensure you have handling for all uncaught exceptions
 Keep it simple: do what must be done, but no more
 Complex handling for uncaught exceptions could trigger other uncaught
exceptions, which can be extremely difficult to debug!
 And since uncaught exceptions don’t occur often, the handler probably has not
been tested as much as other modules
 All handlers, at a minimum, should:
 Log the error and stack trace somewhere durable and secure
 Alert the user so the error will be noticed
 If the thread class has a run status, the run status should be set to stopped,
error, or some equivalent
 Requires access to the thread class state
JavaOneJavaOne
75
Uncaught exception handling
 Ideally, the handler should also alert dependent threads
 Can notify controller or parent, which can:
 Restart the thread that got the uncaught exception
 Not recommended! The pipeline could be in an indeterminate state
 Stop the pipeline (safest)
 Set the stopping request object to stop the pipeline
 Since all stages/threads are monitoring, this will bring down the pipeline
 Pipeline won’t hang!
 Controller doesn’t need an explicit message to know thread has
died, if it is monitoring the run status of the pipeline threads
 In fact, the controller doesn’t even need to get involved –
 Just have the uncaught exception handler set the stop request object to stop
JavaOneJavaOne
76
Uncaught exception handling
Where to handle?
Three primary possibilities:
Custom uncaught exception handler
Catch Throwable() in run() method
Finally block in run() method
JavaOneJavaOne
77
Uncaught exception handling
Custom uncaught exception handler
 If a uncaught exception handler is declared and is in scope,
the default uncaught exception handler is NOT invoked
Determine scope:
Per JVM
Per Thread group
Per Runnable class
JavaOneJavaOne
78
Uncaught exception handling
Custom uncaught exception handler – per JVM scope
Logging the error and alerting the user is about all that can
be done
Since this is per-JVM, it does not have access to any specific
thread classes or thread groups
Set via the static Thread method
setDefaultUncaughtExceptionHandler
Thread.setDefaultUncaughtExceptionHandler(
Thread.UncaughtExceptionHandler ueh)
 ueh is a class that must implement uncaughtException(Thread thr,
Throwable the)
JavaOneJavaOne
79
Uncaught exception handling
Custom uncaught exception handler – per Thread group
Can guarantee standard handling for a group of threads by
having their Thread instance use the same custom
ThreadGroup class
Custom ThreadGroup class extends ThreadGroup and
overrides the uncaughtException method
This is a good choice for a “default” exception handler
Allows for common code for the thread group, but doesn’t have
access to individual Runnable classes
JavaOneJavaOne
80
Uncaught exception handling
Custom uncaught exception handler – per Thread class
Can have access to the Runnable class, so the handler can log
details about the class structure, set run status, etc. before
exiting
Guaranteed to be invoked
Set via the Thread method setUncaughtExceptionHandler
setUncaughtExceptionHandler(
Thread.UncaughtExceptionHandler ueh)
 ueh is a class that must implement uncaughtException(Thread thr,
Throwable the)
 Simplest design is to have ueh be the Runnable class
JavaOneJavaOne
81
Uncaught exception handling
Catch Throwable() in run() method
In general, this is NOT recommended
 Bad form
 If you do this, do it outside any loops in the thread run method, i.e.
at the highest level possible.
 Otherwise, the exception will not trigger the thread to exit, which can
cause very strange thread conditions!
 Thread can be “alive”, but constantly cycling through errors, or hanging
JavaOneJavaOne
82
Uncaught exception handling
Finally block in run() method
Have handled flag that is set to true at end of try block and
every catch block
!handled = uncaught exception
Advantage: Can have handling customized to the invoked
class
 Can set run status and stop request
Disadvantages
 Every catch block must set “handled” flag or the checked exception
will be treated as unhandled
 Default uncaught exception handler still invoked
JavaOneJavaOne
83
Uncaught exception handling
 Critical threads
 Some threads may be critical to your application
 If they stop unexpectedly, the application will not function
 Best to stop the entire application when this occurs
 The uncaught exception handling for the thread should call
System.exit(<non-zero value>)
 If the ThreadGroup uncaught exception handler is guaranteed to be invoked,
then can have a separate critical thread ThreadGroup
 All critical threads are part of this group
 The group handler calls system.exit()
JavaOneJavaOne
84
Example using finally block
public class StageRunnable implements Runnable {
boolean isRunning;
StageWorker worker;
boolean handled;
StageRunnable(StageWorker worker) {
this.worker = worker;
handled = false;
}
JavaOneJavaOne
85
Example using finally block
run() {
try {
isRunning = true;
worker.work();
handled = true;
}
finally {
if (!handled) {
// uncaught exception!
isRunning = false;
worker.setStopRequest(true);
// log error and stack trace to error file
}
}
}
}
JavaOneJavaOne
86
Example using custom handler
public class StageRunnable implements Runnable,
Thread.uncaughtExceptionHandler {
boolean isRunning;
StageWorker worker;
StageRunnable(StageWorker worker) {
this.worker = worker;
}
JavaOneJavaOne
87
Example using custom handler
public void uncaughtException {Thread thr, Throwable the)
isRunning = false;
worker.setStopRequest(true);
// log error and stack trace to error file
}
}
Add to where the actual thread is created:
stageThread.setUncaughtExceptionHandler(stageRunnable);
JavaOneJavaOne
88
Shutdown hooks
 Can declare a special thread to run at shutdown of the JVM
 This is added via System.addShutdownHook(Thread hook)
 Typical usage would be to delete/close files or other resources that
didn’t get deleted/closed normally
 Shutdown hooks should be quick!
 Users don’t like waiting for the JVM to stop
 If the computer is stopping, there may not be much time before the
process is killed
JavaOneJavaOne
89
Shutdown hooks
 Ideally, only use to clean up resources for abnormal JVM termination
 Then in most cases, there is nothing for the shutdown hook to do
 Multiple shutdown hooks can be declared
 Order of execution is not guaranteed
 Make sure there are no dependencies between shutdown hooks
 Eliminate the dependencies, or
 Combine dependent shutdown hooks into one hook
 Shutdown hook threads run concurrently with any other threads still
running
 For example, they will run concurrently with any daemon threads still running
JavaOneJavaOne
90
Daemon Threads
Daemon threads exist only as long as there is one user
(non-daemon) thread running
They will stop abruptly when the last user thread stops
They will not stop on their own any sooner
It’s best to explicitly ask them to stop when they are no
longer needed
JavaOneJavaOne
91
Daemon Threads
 Daemon threads are useful for threads that do ‘side-work’ and you
don’t want to keep the JVM running if all user threads are stopped
 For example, a performance monitor thread
 Very useful for a helper module that is embedded in another and
creates extra threads
 Enclosing module is unaware of these extra threads
 If the last enclosing module thread stops and helper module isn’t
notified, the extra helper module threads will keep the JVM from
stopping unless they are daemon threads
JavaOneJavaOne
92
Daemon Threads
Daemon threads should always do their own cleanup
If cleanup is necessary, put in finally block
Could add a shutdown hook to do cleanup for the daemon
threads
But there is no guarantee that it will run after the daemon
thread stops
JavaOneJavaOne
93
Summary
A well-balanced pipeline can increase throughput,
responsiveness, and processor utilization significantly
Proper thread control and communication is the key to a
successful pipeline
Buffering between stages can reduce synchronization costs
significantly
A framework for stopping threads and consistent handling
of uncaught exceptions is essential to avoid hanging
JavaOneJavaOne
94
IBM at Oracle Open World / JavaOne
 See IBM in each of these areas throughout the OOW event:
• JD Edwards Pavilion at the InterContinental Hotel Level 3… IBM Booth #HIJ-012
• Moscone West ….Guardium Booth #3618
• Java One Expo Floor at the Hilton San Francisco Union Square…IBM Booth #5104
• ILOG at the Java One Expo at the Hilton San Francisco Union Square….IBM Booth #5104
 Meet with IBM experts at our “Solution Spotlight Sessions” in Moscone South, Booth #1111.
 Access a wealth of insight including downloadable whitepapers & client successes at
ibm.com/oracle.
For the most current OOW updates follow us on Twitter at www.twitter.com/IBMandOracle
Phillip Koza
pkoza@us.ibm.com
JavaOneJavaOne Thank YouThank You

More Related Content

What's hot

Whoops! where did my architecture go?
Whoops! where did my architecture go?Whoops! where did my architecture go?
Whoops! where did my architecture go?Oliver Gierke
 
Developing Agile Java Applications using Spring tools
Developing Agile Java Applications using Spring toolsDeveloping Agile Java Applications using Spring tools
Developing Agile Java Applications using Spring toolsSathish Chittibabu
 
Jvm performance tuning
Jvm performance tuningJvm performance tuning
Jvm performance tuningIgor Igoroshka
 
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...Edureka!
 
MULTITHREADING CONCEPT
MULTITHREADING CONCEPTMULTITHREADING CONCEPT
MULTITHREADING CONCEPTRAVI MAURYA
 
Writing Stored Procedures in Oracle RDBMS
Writing Stored Procedures in Oracle RDBMSWriting Stored Procedures in Oracle RDBMS
Writing Stored Procedures in Oracle RDBMSMartin Toshev
 
Pipeline based deployments on Jenkins
Pipeline based deployments  on JenkinsPipeline based deployments  on Jenkins
Pipeline based deployments on JenkinsKnoldus Inc.
 
Java review00
Java review00Java review00
Java review00saryu2011
 
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...Vadym Kazulkin
 
Tomcat Configuration (1)
Tomcat Configuration (1)Tomcat Configuration (1)
Tomcat Configuration (1)nazeer pasha
 
Shopzilla On Concurrency
Shopzilla On ConcurrencyShopzilla On Concurrency
Shopzilla On ConcurrencyRodney Barlow
 

What's hot (20)

Whoops! where did my architecture go?
Whoops! where did my architecture go?Whoops! where did my architecture go?
Whoops! where did my architecture go?
 
Java 9 Features
Java 9 FeaturesJava 9 Features
Java 9 Features
 
Java 8 Overview
Java 8 OverviewJava 8 Overview
Java 8 Overview
 
De Java 8 a Java 11 y 14
De Java 8 a Java 11 y 14De Java 8 a Java 11 y 14
De Java 8 a Java 11 y 14
 
Developing Agile Java Applications using Spring tools
Developing Agile Java Applications using Spring toolsDeveloping Agile Java Applications using Spring tools
Developing Agile Java Applications using Spring tools
 
Jvm performance tuning
Jvm performance tuningJvm performance tuning
Jvm performance tuning
 
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...
Java Threads Tutorial | Multithreading In Java Tutorial | Java Tutorial For B...
 
MULTITHREADING CONCEPT
MULTITHREADING CONCEPTMULTITHREADING CONCEPT
MULTITHREADING CONCEPT
 
Lecture6
Lecture6Lecture6
Lecture6
 
Concurrency in Java
Concurrency in JavaConcurrency in Java
Concurrency in Java
 
Servlets
ServletsServlets
Servlets
 
Java introduction
Java introductionJava introduction
Java introduction
 
Writing Stored Procedures in Oracle RDBMS
Writing Stored Procedures in Oracle RDBMSWriting Stored Procedures in Oracle RDBMS
Writing Stored Procedures in Oracle RDBMS
 
Java 9
Java 9Java 9
Java 9
 
Pipeline based deployments on Jenkins
Pipeline based deployments  on JenkinsPipeline based deployments  on Jenkins
Pipeline based deployments on Jenkins
 
Java review00
Java review00Java review00
Java review00
 
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...
Highlights from Java 10, 11 and 12 and Future of Java at Javaland 2019 By Vad...
 
Java8 - Under the hood
Java8 - Under the hoodJava8 - Under the hood
Java8 - Under the hood
 
Tomcat Configuration (1)
Tomcat Configuration (1)Tomcat Configuration (1)
Tomcat Configuration (1)
 
Shopzilla On Concurrency
Shopzilla On ConcurrencyShopzilla On Concurrency
Shopzilla On Concurrency
 

Viewers also liked

Efficient Memory and Thread Management in Highly Parallel Java Applications
Efficient Memory and Thread Management in Highly Parallel Java ApplicationsEfficient Memory and Thread Management in Highly Parallel Java Applications
Efficient Memory and Thread Management in Highly Parallel Java ApplicationsPhillip Koza
 
Richelle Rasmussen Resume 2016
Richelle Rasmussen Resume 2016Richelle Rasmussen Resume 2016
Richelle Rasmussen Resume 2016Richelle Rasmussen
 
Professional profile of malik javeed
Professional profile of malik javeedProfessional profile of malik javeed
Professional profile of malik javeedMalik Javeed
 
ExpectationsContinuousImprovement
ExpectationsContinuousImprovementExpectationsContinuousImprovement
ExpectationsContinuousImprovementDavendra Maharaj
 
Apple vs LG advertising
Apple vs LG advertisingApple vs LG advertising
Apple vs LG advertisingIstvan Meszes
 

Viewers also liked (9)

Blood_CV_J15
Blood_CV_J15Blood_CV_J15
Blood_CV_J15
 
Efficient Memory and Thread Management in Highly Parallel Java Applications
Efficient Memory and Thread Management in Highly Parallel Java ApplicationsEfficient Memory and Thread Management in Highly Parallel Java Applications
Efficient Memory and Thread Management in Highly Parallel Java Applications
 
Richelle Rasmussen Resume 2016
Richelle Rasmussen Resume 2016Richelle Rasmussen Resume 2016
Richelle Rasmussen Resume 2016
 
Professional profile of malik javeed
Professional profile of malik javeedProfessional profile of malik javeed
Professional profile of malik javeed
 
ExpectationsContinuousImprovement
ExpectationsContinuousImprovementExpectationsContinuousImprovement
ExpectationsContinuousImprovement
 
CV-MITE DOJCINOV
CV-MITE DOJCINOVCV-MITE DOJCINOV
CV-MITE DOJCINOV
 
Apple vs LG advertising
Apple vs LG advertisingApple vs LG advertising
Apple vs LG advertising
 
LK CERTI SCANS
LK CERTI SCANSLK CERTI SCANS
LK CERTI SCANS
 
Order Status Flow Chart
Order Status Flow ChartOrder Status Flow Chart
Order Status Flow Chart
 

Similar to Maximizing Throughput and Reliability with Pipelined Tasks

Multi t hreading_14_10
Multi t hreading_14_10Multi t hreading_14_10
Multi t hreading_14_10Minal Maniar
 
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptxsandhyakiran10
 
Lecture 13 threads presentation 16 slides
Lecture 13 threads presentation 16 slidesLecture 13 threads presentation 16 slides
Lecture 13 threads presentation 16 slidesAteeq Ur Rehman
 
Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Robert Scholte
 
Multithreading in java
Multithreading in javaMultithreading in java
Multithreading in javajunnubabu
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8Heartin Jacob
 
Unit-3 MULTITHREADING-2.pdf
Unit-3 MULTITHREADING-2.pdfUnit-3 MULTITHREADING-2.pdf
Unit-3 MULTITHREADING-2.pdfGouthamSoma1
 
Multi threading
Multi threadingMulti threading
Multi threadinggndu
 
Lecture 23-24.pptx
Lecture 23-24.pptxLecture 23-24.pptx
Lecture 23-24.pptxtalha ijaz
 
Multithreading programming in java
Multithreading programming in javaMultithreading programming in java
Multithreading programming in javaElizabeth alexander
 
Lec 1.10 Object Oriented Programming
Lec 1.10 Object Oriented ProgrammingLec 1.10 Object Oriented Programming
Lec 1.10 Object Oriented ProgrammingBadar Waseer
 
Apache Maven supports ALL Java (Javaland 2019)
Apache Maven supports ALL Java (Javaland 2019)Apache Maven supports ALL Java (Javaland 2019)
Apache Maven supports ALL Java (Javaland 2019)Robert Scholte
 
Multithreading and concurrency in android
Multithreading and concurrency in androidMultithreading and concurrency in android
Multithreading and concurrency in androidRakesh Jha
 

Similar to Maximizing Throughput and Reliability with Pipelined Tasks (20)

Multithreading
MultithreadingMultithreading
Multithreading
 
Threading.pptx
Threading.pptxThreading.pptx
Threading.pptx
 
Java multi thread programming on cmp system
Java multi thread programming on cmp systemJava multi thread programming on cmp system
Java multi thread programming on cmp system
 
Multi t hreading_14_10
Multi t hreading_14_10Multi t hreading_14_10
Multi t hreading_14_10
 
Thread
ThreadThread
Thread
 
Thread
ThreadThread
Thread
 
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx
8.-OBJECT-ORIENTED-PROGRAMMING-USING-JAVA-Multithreading.pptx
 
Md09 multithreading
Md09 multithreadingMd09 multithreading
Md09 multithreading
 
Lecture 13 threads presentation 16 slides
Lecture 13 threads presentation 16 slidesLecture 13 threads presentation 16 slides
Lecture 13 threads presentation 16 slides
 
Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)
 
Multithreading in java
Multithreading in javaMultithreading in java
Multithreading in java
 
Working With Concurrency In Java 8
Working With Concurrency In Java 8Working With Concurrency In Java 8
Working With Concurrency In Java 8
 
Unit-3 MULTITHREADING-2.pdf
Unit-3 MULTITHREADING-2.pdfUnit-3 MULTITHREADING-2.pdf
Unit-3 MULTITHREADING-2.pdf
 
Slide 7 Thread-1.pptx
Slide 7 Thread-1.pptxSlide 7 Thread-1.pptx
Slide 7 Thread-1.pptx
 
Multi threading
Multi threadingMulti threading
Multi threading
 
Lecture 23-24.pptx
Lecture 23-24.pptxLecture 23-24.pptx
Lecture 23-24.pptx
 
Multithreading programming in java
Multithreading programming in javaMultithreading programming in java
Multithreading programming in java
 
Lec 1.10 Object Oriented Programming
Lec 1.10 Object Oriented ProgrammingLec 1.10 Object Oriented Programming
Lec 1.10 Object Oriented Programming
 
Apache Maven supports ALL Java (Javaland 2019)
Apache Maven supports ALL Java (Javaland 2019)Apache Maven supports ALL Java (Javaland 2019)
Apache Maven supports ALL Java (Javaland 2019)
 
Multithreading and concurrency in android
Multithreading and concurrency in androidMultithreading and concurrency in android
Multithreading and concurrency in android
 

Recently uploaded

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?Watsoo Telematics
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
buds n tech IT solutions
buds n  tech IT                solutionsbuds n  tech IT                solutions
buds n tech IT solutionsmonugehlot87
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 

Recently uploaded (20)

Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
buds n tech IT solutions
buds n  tech IT                solutionsbuds n  tech IT                solutions
buds n tech IT solutions
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 

Maximizing Throughput and Reliability with Pipelined Tasks

  • 1. Phillip Koza IBM Maximizing Throughput and Reliability with Pipelined Tasks JavaOneJavaOne
  • 2. JavaOneJavaOne 2 Agenda What is pipelining? When to pipeline Creating/starting stages and threads Stage/thread communication Waiting/flushing Stopping stages/threads Uncaught exception handling Shutdown hooks, Daemon threads Summary
  • 5. JavaOneJavaOne 5 What is pipelining? Pipelining is processing a given job as a series of cooperating, dependent, sequential stages Each stage does a subset of the processing, then hands off to the next stage Each stage is a separate thread or threads Each stage has at least one input queue and at least one output queue These queues may be logical Don’t want a stage to get too far ahead of its successor Stages should block if they are too far ahead
  • 6. JavaOneJavaOne 6 What is pipelining? Well understood and utilized concept in microprocessors: almost all processor chips are heavily pipelined  Pipelining is operator-based parallelism, as opposed to data (partition-based) parallelism  Each stage executes in parallel a subset of the operations that need to be performed on all objects/tasks  Partition based parallelism executes in parallel all operations on a subset of the objects/tasks Both forms of parallelism can be utilized at once!
  • 7. JavaOneJavaOne 7 Example – Stock data app StoreStore ParseParse Read allRead all stockstock datadata TechnologyTechnology stockstock data subscriberdata subscriber CommodityCommodity stockstock data subscriberdata subscriber Financial stockFinancial stock data subscriberdata subscriber
  • 8. JavaOneJavaOne 8 Why pipelining? Increased throughput , responsiveness, and processor utilization If n stages, a well balanced pipeline can increase cpu utilization and throughput by a factor of close to n Other stages can continue processing if a stage must perform I/O Flexibility: easy to add additional processing – just add another stage! Maintainability: code follows the pipeline – harder to have monolithic 3000 line methods that do everything!
  • 9. JavaOneJavaOne 9 Pipeline topologies Basic: Single producer to single consumer Pipelining + partitioned input processing: multiple producers to single consumer Each producer processes a partition of the input Pipelining + partitioned output processing: single producer to multiple consumers Each consumer processes a partition of the output Multiple producers + multiple consumers Complicated: if possible, have separate pipelines!
  • 10. JavaOneJavaOne 10 When to pipeline Complex job with multiple processing modules Stage candidates: when should you consider having a module run as a separate stage? Running in a separate thread is not free: must consider additional startup, synchronization, complexity The benefits must be weighed against these additional costs Luckily, there are ways to minimize these costs! A key to effective pipelining is determining which modules to run as pipeline stages
  • 11. JavaOneJavaOne 11 When to pipeline Module does I/O Module does significant processing that is not interleaved with that of other stages Profiling shows this module is a bottleneck
  • 12. JavaOneJavaOne 12 When to pipeline Ideally, all stages are perfectly balanced: if n stages, each stage does 1/n of the work Each stage then never waits for input (except at startup) and never waits to deliver output If not perfectly balanced, some stages may get ahead of the others These stages should block until the other stages catch up Number of stages is usually statically fixed when the pipeline starts
  • 13. JavaOneJavaOne 13 Partition parallelism  Partition parallelism is having separate threads process a portion (partition) of the data stream  The partitions are not necessarily disjoint  Can be utilized whenever objects can be processed in any order, OR you know how to merge them into the correct order  Can be used to increase overall throughput, or throughput of individual stages  If objects can be processed in any order, can have an independent pipeline for each partition  Overhead may be too high if some stages are very lightweight  If dependencies, must merge the streams at some point – so need a common pipeline  Partition threads can be allocated statically or dynamically
  • 14. JavaOneJavaOne 14 How many threads? Keep track of how often consumers wait for producers and vice-versa Lots of consumer waits = more producer threads Lots of producer waits = more consumer threads This can mean adding more pipelines, more pipeline stages, or more threads per stage Adding more threads to slow stages is particularly useful for balancing stages
  • 15. JavaOneJavaOne 15 When to pipeline Example: Determine stage boundaries To compile a SQL query, the SQL compiler must: Lexically analyze the query Parse the token stream from the lexer Bind objects (table, column, etc) Normalize Optimize Generate query plan Currently one thread is doing all of the above processing
  • 16. JavaOneJavaOne 16 When to pipeline Example: Determine stage boundaries Analysis shows that: Lexer, Parser and Binder use significant CPU and can do I/O (catalog table lookups)  But calls to these modules can be interleaved, so should not be split  Binding a view will require the underlying query expression to be lexically analyzed and parsed Normalizer, optimizer, and code generator all use significant CPU and these calls are not interleaved
  • 17. JavaOneJavaOne 17 When to pipeline Example: Determine stage boundaries Split into the following stages: Lexer/Parser/Binder Normalizer Optimizer Code generator  Each stage can then execute in parallel Normalization, optimization, and code generation can continue if the Binder must do I/O Each stage of processing proceeds in parallel
  • 19. JavaOneJavaOne 19 Creating threads ThreadPoolExecutor Implements ExecutorService Best when have lots of independent short running tasks that terminate themselves Provides automatic thread reuse via pooling Pooling pays off big for short running tasks
  • 20. JavaOneJavaOne 20 Creating threads ThreadPoolExecutor Creates threads via ThreadFactory Default is Executors.defaultThreadFactory Can create your own and set via setThreadFactory Can specify own thread name, priority, group, etc
  • 21. JavaOneJavaOne 21 Creating threads  ThreadPoolExecutor  In a pipeline, this can be useful for creating additional threads for partitioned parallelism for a pipeline stage  Each stage has its own ThreadPoolExecutor  Threads can be added as the stage load increases, returned to the pool when the stage load decreases  Control maximum number of idle threads and total threads by setting corePoolSize and maximumPoolSize  It’s important to limit the maximumPoolSize  Unlimited growth in the number of threads can quickly exhaust all resources
  • 22. JavaOneJavaOne 22 Creating threads ThreadPoolExecutor Unless an unlimited maximumPoolSize is specified, a request for another thread will block waiting for a thread to become available If no more threads immediately available, would rather just use one of the existing threads So use a SynchronousQueue as the work queue Using the default RejectedExecutionHandler, the request will be rejected if the maximum number of threads are already in use  i.e. a RejectedExecutionException will be thrown
  • 23. JavaOneJavaOne 23 Using ThreadPoolExecutor private static final maxThreads = 5; private SynchronousQueue syncQ = new SynchronousQueue(); private ExecutorService threadPool = new ThreadPoolExecutor(maxThreads, maxThreads, 60, TimeUnit.SECONDS,syncQ); public boolean addWorkerThread(StageWorker worker) { try { threadPool.execute(new StageRunnable(worker)); } catch (RejectedExecutionException) { return false; } return true; }
  • 24. JavaOneJavaOne 24 Creating threads Raw threads Gives maximum control over when threads are created, started, and stopped The best choice when you have long running dependent tasks, i.e. a pipeline Pipelines need maximum control over their threads All stage threads should be up, or all should be down Need precise control over the timing of starting and stopping threads
  • 25. JavaOneJavaOne 25 Creating threads  Pooling potentially useful, but not as important  Thread creation is not the dominant cost  Be very careful if have one giant thread pool for all stages and pipelines!  A pipeline does not function unless all stages are executing  Don’t want some pipeline stages to be queued awaiting execution while others are running  If need to limit the total number of threads, it is best to limit the number of pipelines  For a pipeline, raw threads are the best choice – for now, at least!
  • 26. JavaOneJavaOne 26 Using raw threads private static final maxThreads = 5; private threadCount = 0; private final List<Thread> threadList = new ArrayList<Thread>(maxThreads); public boolean addWorkerThread(StageWorker worker) { if (threadCount < maxThreads) { Thread stageThread = new Thread(new StageRunnable(worker)); threadList.add(stageThread); threadCount++; stageThread.start(); return true; } return false; }
  • 27. JavaOneJavaOne 27 Starting threads Two basic control models: MVC (Model/View/Controller) Waterfall (hierarchical)
  • 28. JavaOneJavaOne 28 Starting threads - MVC Model is the data flow View is presentation of the monitoring data/return data Controller logic is kept separate Dedicated controller thread Controller must be aware of all stages/threads, how to start them, and how they are linked Controller can precisely control which threads get created first
  • 29. JavaOneJavaOne 29 Starting threads - MVC Controller starts all stages/threads when the pipeline starts Messages/callbacks to the controller are used to restart or add additional stages/threads Controller must ensure predecessor and successor stages properly handle this Controller can monitor pipeline state If a stage thread dies unexpectedly, can restart the stage But safest and easiest thing to do is to bring down the entire pipeline
  • 30. JavaOneJavaOne 30 MVC Diagram Stage 3Stage 3 Sink Source ControllerController Stage 2Stage 2 Stage 1Stage 1
  • 31. JavaOneJavaOne 31 Starting threads - Waterfall No dedicated control thread Start from the head of the pipeline, i.e. the final consumer stage/thread Each successor (parent) stage creates any immediate predecessor (child) stage threads that it needs Control “falls” from parent to child, hence the name If any child stage/thread dies, parent must notice and handle (restart child, stop itself, etc)
  • 32. JavaOneJavaOne 32 Starting threads - Waterfall In effect, each parent thread acts as the controller for the child If additional child threads for a stage are needed, the parent creates them  Siblings should not create additional siblings – only a parent should! (the parent may be quite happy with the number of children it already has!)
  • 33. JavaOneJavaOne 33 Waterfall Diagram Stage 3Stage 3 Sink Source Stage 2Stage 2 Stage 1Stage 1 ChildChild ParentParent ChildChild ParentParent createscreates createscreates
  • 34. JavaOneJavaOne 34 Starting threads MVC advantages Components do not need to know who their predecessors or successors are All pipeline control logic is in one place  Easy to refactor code to add/remove stages  Makes maintenance easier MVC disadvantages Must be careful to avoid starting a predecessor stage before the successor is ready
  • 35. JavaOneJavaOne 35 Starting threads Waterfall advantages Parent has complete control of its child  Can start and stop child threads as it pleases Parent can easily guarantee that the child is not started until the parent is ready Waterfall disadvantages Logic to start/stop stages is in each successor stage  Harder to add/remove stages  Each stage has its predecessor hard-coded  Logic can become subtly different over time  Separate logic harder to find, maintain
  • 36. JavaOneJavaOne 36 Stage/thread communication  How do you move data from one stage to the next?  Single producer to single consumer  Producer adds data to [logical] output queue, consumer reads  Multiple producers to single consumer  Each producer adds data to its [logical] output queue, consumer reads from each producer queue, merging output if necessary  Single producer to multiple consumers, consumers process any available data  Producer adds data to a single [logical] output queue, each consumer reads next available
  • 37. JavaOneJavaOne 37 Stage/thread communication  Single producer to multiple consumers, consumers process a partition of the data  Each consumer requires a not necessarily distinct subset of the data  Two potential models: push vs. pull  Push: producer determines what data to give to each consumer, and then sends it to each  Producer has to know what the consumer wants  Producer must allocate time to do this  Producer may have data to give, but consumer is not ready  Consumer may be ready for data, and the producer may have data to give, but the producer is busy doing other things
  • 38. JavaOneJavaOne 38 Stage/thread communication Pull: Consumer gets the data it needs directly from the producer Producer doesn’t need to spend time determining what data a consumer needs and sending it If data is available, consumer doesn’t have to wait for the producer to send it  Requires consumer to access producer data structures – which means synchronization! Pull has the potential to perform better, but is more complicated
  • 39. JavaOneJavaOne 39 Push Example – Stock data app Store,Store, DistributeDistribute ParseParse Read allRead all stockstock datadata queuequeue queuequeue queuequeue TechnologyTechnology stockstock data subscriberdata subscriber CommodityCommodity stockstock data subscriberdata subscriber Financial stockFinancial stock data subscriberdata subscriber
  • 40. JavaOneJavaOne 40 Pull Example – Stock data app StoreStoreParseParse Read allRead all stockstock datadata SynchSynch AccessAccess to storeto store SynchSynch AccessAccess to storeto store SynchSynch AccessAccess to storeto store TechnologyTechnology stockstock data subscriberdata subscriber Financial stockFinancial stock data subscriberdata subscriber CommodityCommodity stockstock data subscriberdata subscriber
  • 42. JavaOneJavaOne 42 Stage/thread communication  PipedOutputStream, PipedInputStream  Advantages:  Can layer the wide variety of stream classes to do transforms, etc.  Synchronization, waiting, notification is handled for you  A full output pipe automatically forces a producer that is too fast to slow down  Buffer size expressed in bytes – great if you want to strictly control the memory used  Disadvantages  All objects must be serialized – not so great if you are not ultimately writing to disk  Must be 1:1 – one producer and one consumer (per pipe)  Push only
  • 43. JavaOneJavaOne 43 Producer w/ Pipes public class Stage1 implements StageWorker{ private PipedOutputStream outPipe; Stage1(Stage successor) { outPipe = new PipedOutputStream(successor.inPipe); } … private void sendData(WorkUnit workUnit) { ObjectOutputStream outObjStream = new ObjectOutputStream(outPipe); workUnit.writeObject(outObjStream); } }
  • 44. JavaOneJavaOne 44 Consumer w/ Pipes public class Stage2 implements StageWorker { public PipedInputStream inPipe; Stage2() { inPipe = new PipedInputStream(); } … private WorkUnit receiveData() { ObjectInputStream inObjStream = new ObjectInputStream(inPipe); WorkUnit workUnit = new WorkUnit(); workUnit.readObject(inObjStream); return workUnit; } }
  • 45. JavaOneJavaOne 45 Stage/thread communication  Synchronized structures + wait/notify  Advantages:  Allows multiple consumers to access upstream data at their own pace, i.e. they can pull their data instead of having it pushed to them  Consumers determine what data they want  Disadvantages:  Producers and consumers must synchronize on the same object  Must manage synchronization, waiting, notification yourself  This includes making the producer wait if consumers are falling behind  Cannot read while writing and vice-versa
  • 46. JavaOneJavaOne 46 Producer w/ Synchronized Access public class Stage1 implements StageWorker { public LinkedList<WorkUnit> outList ; Stage1(Stage successor) { outList = new LinkedList<WorkUnit>(1000); } … private void sendData(WorkUnit workUnit) { synchronized(outList) { outList.add(workUnit); outList.notifyAll(); } }
  • 47. JavaOneJavaOne 47 Consumer w/ Synchronized Access public class Stage2 implements StageWorker { private ArrayList<WorkUnit> inList; public int currentPos = 0; // This needs to be adjusted for removals Stage2(Stage predecessor) { inputList = predecessor.outList; } …
  • 48. JavaOneJavaOne 48 Consumer w/ Synchronized Access private WorkUnit receiveData() { WorkUnit workUnit = null; synchronized(inList) { while (currentPos >= inList.size()) { try { inList.wait(1000); } catch (InterruptedException ie) {} } workUnit = inList.get(currentPos++); } return workUnit; } }
  • 49. JavaOneJavaOne 49 Stage/thread communication  ArrayBlockingQueue, LinkedBlockingQueue  Use the capacity setting to control how far ahead a producer can get before it blocks  Advantages:  Synchronization, waiting, notification is handled for you  A full output queue automatically forces a producer that is too fast to slow down  Can read while writing and vice-versa  Capacity is expressed as a # of objects – great if you want to limit how many objects the producer gets ahead of the consumer  Disadvantages:  Memory use can vary if object sizes are highly variable  There is still a synchronization cost to put/take  Push only
  • 50. JavaOneJavaOne 50 Producer w/ ArrayBlockingQueue public class Stage1 implements StageWorker { private ArrayBlockingQueue outQueue ; Stage1(Stage successor) { outQueue = successor.inQueue; } … private void sendData(WorkUnit workUnit) { outQueue.put(workUnit); } }
  • 51. JavaOneJavaOne 51 Consumer w/ ArrayBlockingQueue public class Stage2 implements StageWorker { public ArrayBlockingQueue<WorkUnit> inQueue; Stage2() { inQueue = new ArrayBlockingQueue<WorkUnit>; } … private WorkUnit receiveData() { WorkUnit workUnit = inQueue.take(); return workUnit; } }
  • 52. JavaOneJavaOne 52 Stage/thread communication Recommendations  Use ArrayBlockingQueue except where there are multiple consumers LinkedBlockingQueue is not recommended, as it is unbounded by default, and has higher memory utilization If multiple consumers, have the consumers pull their data using synchronization + wait/notify
  • 53. JavaOneJavaOne 53 Stage/thread communication  For good performance, it is critical to minimize the synchronization costs of inter-stage communication The key is maximizing the unit of work passed between stages, i.e. buffering  Batch up smaller units of work into buffers of larger ones The buffers are passed between stages instead of the original units of work Buffering can decrease responsiveness The key here is to flush the buffers whenever any thread must wait
  • 54. JavaOneJavaOne 54 Stage/thread communication When using ArrayBlockingQueue: Wrap in a custom queue that buffers objects and puts the buffers to the underlying queue, instead of the actual objects Take from the queue then gets the buffers, and processes them When using synchronized access: Producer buffers objects, then adds full buffers to the synchronized common data structure Consumers read full buffers from the synchronized common data structure
  • 55. JavaOneJavaOne 55 Waiting/Flushing Waiting indefinitely is dangerous! Try to NEVER wait on anything indefinitely If you are waiting for another thread to do something, and it dies, you will be waiting forever So, use loops+timeouts whenever possible  When wake up, check if anyone wants you to stop, process a more urgent request, etc.  If not, re-issue request
  • 56. JavaOneJavaOne 56 Waiting/Flushing Interrupting threads Dangerous to rely on interrupts to break indefinite waits Who will send the interrupt and how will they know it’s needed?  Interrupting thread must have a handle to the interrupted thread
  • 57. JavaOneJavaOne 57 Waiting/Flushing Interrupting threads Could interrupt an I/O in process. The results of this are unpredictable:  InterruptedIOException  I/O could have partially completed  ClosedByInterruptException (if I/O was through a channel)  Ignored  For example, if thread is blocked waiting on a socket (ServerSocket.accept) Even if your module handles interrupts correctly – can you be sure all called modules do? Best to avoid using interrupts!
  • 58. JavaOneJavaOne 58 Waiting/Flushing Flush all buffers before waiting Otherwise already processed data can get “stuck” in the pipeline Optimization: First wait with a short timeout, and then if still no data, flush at that point
  • 59. JavaOneJavaOne 59 Stopping Requesting stop via thread interruption If thread is interrupted, it assumes it should stop  This is how ExecutorService.shutdownNow() and Future.cancel() signal threads to stop  So threads that stop this way will be stoppable if run as part of an ExecutorService  BUT:
  • 60. JavaOneJavaOne 60 Stopping Requesting stop via thread interruption Class has to run as a thread, and it needs to know it is running as a thread  If thread is sleeping or waiting, InterrruptException will be thrown which will clear the interrupted state  The catch of InterruptedException has to signal the class to stop or has to re-interrupt the thread  Has all the problems mentioned earlier if an I/O is interrupted  No granularity in the stop request  Cannot distinguish between stop immediately and stop gracefully So this is not recommended!
  • 61. JavaOneJavaOne 61 Stopping Requesting stop via flag objects Have a stop request object that indicates thread should stop Classes check regularly, and always before sleeping, waiting, I/O, putting/getting from a blocking queue, etc. Works the same regardless of whether the class is running as a thread or not Stop request object can indicate different types of stop: stop immediate, stop gracefully (finish work in progress), etc.  Stopping gracefully is important in a pipeline – in most cases, you don’t want to lose the work already completed!
  • 62. JavaOneJavaOne 62 Stopping Have a stop request object that indicates thread should stop Can have a single stop request object for the entire pipeline that all threads monitor  But this only allows the entire pipeline to be stopped For finer granularity of stop control, have a pipeline stop request object with references to stage/thread stop request objects Setting of stop request object must be synchronized – but this does not occur very often
  • 63. JavaOneJavaOne 63 Stopping Have a request stop object that indicates thread should stop Reading of the stop request object will occur frequently Reading stop request object does not need to be synchronized for most pipeline applications  It is not critical to see a stop request instantaneously, and synchronization doesn’t guarantee this anyway  The stop request is typically a boolean or enum, so updates of it are atomic  There will be enough other synchronization boundaries crossed to guarantee the stop request object modification will be seen  Puts/gets to blocking queues, synchronized access to other shared structures, etc.  Synchronizing on write but not on read is known as Asymmetrical Locking
  • 64. JavaOneJavaOne 64 Stopping Detecting a stage/thread has actually stopped Could use Thread.isAlive() to detect if a thread has stopped This requires a handle to the thread Presumes the class is running as a thread Won’t work for higher abstractions, such as a stage or pipeline
  • 65. JavaOneJavaOne 65 Stopping Detecting a stage/thread has actually stopped Better to make this abstract Separate Runnable class from class that does the real work Runnable class invokes the work class The Runnable class has an “isRunning” object that tracks the run status All threads use this common Runnable class Guarantees all threads have a common mechanism for tracking run status Can also be used to guarantee common handling for uncaught exceptions
  • 66. JavaOneJavaOne 66 Stopping Detecting a stage/thread has actually stopped The status of a stage is the logical-AND of the status of the individual threads of that stage The status of a pipeline is the logical-AND of the status of the stages If a graceful stop is requested, stages must wait for their predecessor stages to actually stop before they can stop This allows in-flight data to be processed
  • 67. JavaOneJavaOne 67 Stopping Unexpected thread termination Just set the stop request object to bring down all related threads Easiest and safest thing to do is bring down entire pipeline
  • 68. JavaOneJavaOne 68 Stopping Returning control to the user Controller or highest level pipeline thread must make sure all threads are truly stopped before returning Strange things can happen if you try to start a pipeline and some threads from its previous incarnation are still running! Could call thread.join()  But must have handle to all threads, and can’t be responsive to other requests Better for the controller to query the isRunning flag of all thread classes and wait for all to be stopped.
  • 69. JavaOneJavaOne 69 Example: buffering, flushing, stopping work() { while (!checkForStopRequests()) { int outBufSize = 100; ArrayList<WorkUnit> outBuf = new ArrayList<WorkUnit>(bufSize); ArrayList<WorkUnit> inBuf = inQueue.poll(1000,TimeUnit.MILLISECONDS); // If have to wait for input, flush output if (inBuf == null) { if (outBuf.size() > 0) { flushOutput(); } }
  • 70. JavaOneJavaOne 70 Example: buffering, flushing, stopping else { for (WorkUnit workUnit : inBuf) { // process workUnit … outBuf.add(workUnit); if (outBuf.size() > outBufSize) { flushOutput(); } } } }
  • 71. JavaOneJavaOne 71 Example: buffering, flushing, stopping flushOutput() { boolean success = false; while (!success && !checkForStopRequests()) { success = outQueue.offer(outBuf,1000,TimeUnit.MILLISECONDS); } } Boolean checkForStopRequests() { // check for stop requests. Basic handling is: if (stop requested) { stageRunnableObj.isRunning = false; return true; // stop this stage } return false; }
  • 72. JavaOneJavaOne 72 Uncaught exception handling  Proper handling for uncaught exceptions is absolutely critical for a pipeline!  Uncaught exceptions are typically the leading cause of unexpected thread termination  Since all threads are dependent on others, if one goes down, the entire pipeline can hang!  A hung pipeline can be hard to detect  Is it hung, or just in-between bursts of traffic?  Proper monitoring statistics can help detect a hung pipeline  It can take a while before you can be sure  Auto-aborting a pipeline that is perceived to be hung will inevitably abort too soon in certain situations  So typically requires human intervention  The best way to handle a hung pipeline is to prevent it!
  • 73. JavaOneJavaOne 73 Uncaught exception handling By default, uncaught exceptions are handled by the default uncaught exception handler This just writes the stack trace to standard error This is rarely acceptable!  Stack trace may be lost  If class tracks its run status, this will be inaccurate after an uncaught exception: run status will still be ‘running’  What about threads that are dependent on this thread? Don’t let the default happen to you!
  • 74. JavaOneJavaOne 74 Uncaught exception handling  Ensure you have handling for all uncaught exceptions  Keep it simple: do what must be done, but no more  Complex handling for uncaught exceptions could trigger other uncaught exceptions, which can be extremely difficult to debug!  And since uncaught exceptions don’t occur often, the handler probably has not been tested as much as other modules  All handlers, at a minimum, should:  Log the error and stack trace somewhere durable and secure  Alert the user so the error will be noticed  If the thread class has a run status, the run status should be set to stopped, error, or some equivalent  Requires access to the thread class state
  • 75. JavaOneJavaOne 75 Uncaught exception handling  Ideally, the handler should also alert dependent threads  Can notify controller or parent, which can:  Restart the thread that got the uncaught exception  Not recommended! The pipeline could be in an indeterminate state  Stop the pipeline (safest)  Set the stopping request object to stop the pipeline  Since all stages/threads are monitoring, this will bring down the pipeline  Pipeline won’t hang!  Controller doesn’t need an explicit message to know thread has died, if it is monitoring the run status of the pipeline threads  In fact, the controller doesn’t even need to get involved –  Just have the uncaught exception handler set the stop request object to stop
  • 76. JavaOneJavaOne 76 Uncaught exception handling Where to handle? Three primary possibilities: Custom uncaught exception handler Catch Throwable() in run() method Finally block in run() method
  • 77. JavaOneJavaOne 77 Uncaught exception handling Custom uncaught exception handler  If a uncaught exception handler is declared and is in scope, the default uncaught exception handler is NOT invoked Determine scope: Per JVM Per Thread group Per Runnable class
  • 78. JavaOneJavaOne 78 Uncaught exception handling Custom uncaught exception handler – per JVM scope Logging the error and alerting the user is about all that can be done Since this is per-JVM, it does not have access to any specific thread classes or thread groups Set via the static Thread method setDefaultUncaughtExceptionHandler Thread.setDefaultUncaughtExceptionHandler( Thread.UncaughtExceptionHandler ueh)  ueh is a class that must implement uncaughtException(Thread thr, Throwable the)
  • 79. JavaOneJavaOne 79 Uncaught exception handling Custom uncaught exception handler – per Thread group Can guarantee standard handling for a group of threads by having their Thread instance use the same custom ThreadGroup class Custom ThreadGroup class extends ThreadGroup and overrides the uncaughtException method This is a good choice for a “default” exception handler Allows for common code for the thread group, but doesn’t have access to individual Runnable classes
  • 80. JavaOneJavaOne 80 Uncaught exception handling Custom uncaught exception handler – per Thread class Can have access to the Runnable class, so the handler can log details about the class structure, set run status, etc. before exiting Guaranteed to be invoked Set via the Thread method setUncaughtExceptionHandler setUncaughtExceptionHandler( Thread.UncaughtExceptionHandler ueh)  ueh is a class that must implement uncaughtException(Thread thr, Throwable the)  Simplest design is to have ueh be the Runnable class
  • 81. JavaOneJavaOne 81 Uncaught exception handling Catch Throwable() in run() method In general, this is NOT recommended  Bad form  If you do this, do it outside any loops in the thread run method, i.e. at the highest level possible.  Otherwise, the exception will not trigger the thread to exit, which can cause very strange thread conditions!  Thread can be “alive”, but constantly cycling through errors, or hanging
  • 82. JavaOneJavaOne 82 Uncaught exception handling Finally block in run() method Have handled flag that is set to true at end of try block and every catch block !handled = uncaught exception Advantage: Can have handling customized to the invoked class  Can set run status and stop request Disadvantages  Every catch block must set “handled” flag or the checked exception will be treated as unhandled  Default uncaught exception handler still invoked
  • 83. JavaOneJavaOne 83 Uncaught exception handling  Critical threads  Some threads may be critical to your application  If they stop unexpectedly, the application will not function  Best to stop the entire application when this occurs  The uncaught exception handling for the thread should call System.exit(<non-zero value>)  If the ThreadGroup uncaught exception handler is guaranteed to be invoked, then can have a separate critical thread ThreadGroup  All critical threads are part of this group  The group handler calls system.exit()
  • 84. JavaOneJavaOne 84 Example using finally block public class StageRunnable implements Runnable { boolean isRunning; StageWorker worker; boolean handled; StageRunnable(StageWorker worker) { this.worker = worker; handled = false; }
  • 85. JavaOneJavaOne 85 Example using finally block run() { try { isRunning = true; worker.work(); handled = true; } finally { if (!handled) { // uncaught exception! isRunning = false; worker.setStopRequest(true); // log error and stack trace to error file } } } }
  • 86. JavaOneJavaOne 86 Example using custom handler public class StageRunnable implements Runnable, Thread.uncaughtExceptionHandler { boolean isRunning; StageWorker worker; StageRunnable(StageWorker worker) { this.worker = worker; }
  • 87. JavaOneJavaOne 87 Example using custom handler public void uncaughtException {Thread thr, Throwable the) isRunning = false; worker.setStopRequest(true); // log error and stack trace to error file } } Add to where the actual thread is created: stageThread.setUncaughtExceptionHandler(stageRunnable);
  • 88. JavaOneJavaOne 88 Shutdown hooks  Can declare a special thread to run at shutdown of the JVM  This is added via System.addShutdownHook(Thread hook)  Typical usage would be to delete/close files or other resources that didn’t get deleted/closed normally  Shutdown hooks should be quick!  Users don’t like waiting for the JVM to stop  If the computer is stopping, there may not be much time before the process is killed
  • 89. JavaOneJavaOne 89 Shutdown hooks  Ideally, only use to clean up resources for abnormal JVM termination  Then in most cases, there is nothing for the shutdown hook to do  Multiple shutdown hooks can be declared  Order of execution is not guaranteed  Make sure there are no dependencies between shutdown hooks  Eliminate the dependencies, or  Combine dependent shutdown hooks into one hook  Shutdown hook threads run concurrently with any other threads still running  For example, they will run concurrently with any daemon threads still running
  • 90. JavaOneJavaOne 90 Daemon Threads Daemon threads exist only as long as there is one user (non-daemon) thread running They will stop abruptly when the last user thread stops They will not stop on their own any sooner It’s best to explicitly ask them to stop when they are no longer needed
  • 91. JavaOneJavaOne 91 Daemon Threads  Daemon threads are useful for threads that do ‘side-work’ and you don’t want to keep the JVM running if all user threads are stopped  For example, a performance monitor thread  Very useful for a helper module that is embedded in another and creates extra threads  Enclosing module is unaware of these extra threads  If the last enclosing module thread stops and helper module isn’t notified, the extra helper module threads will keep the JVM from stopping unless they are daemon threads
  • 92. JavaOneJavaOne 92 Daemon Threads Daemon threads should always do their own cleanup If cleanup is necessary, put in finally block Could add a shutdown hook to do cleanup for the daemon threads But there is no guarantee that it will run after the daemon thread stops
  • 93. JavaOneJavaOne 93 Summary A well-balanced pipeline can increase throughput, responsiveness, and processor utilization significantly Proper thread control and communication is the key to a successful pipeline Buffering between stages can reduce synchronization costs significantly A framework for stopping threads and consistent handling of uncaught exceptions is essential to avoid hanging
  • 94. JavaOneJavaOne 94 IBM at Oracle Open World / JavaOne  See IBM in each of these areas throughout the OOW event: • JD Edwards Pavilion at the InterContinental Hotel Level 3… IBM Booth #HIJ-012 • Moscone West ….Guardium Booth #3618 • Java One Expo Floor at the Hilton San Francisco Union Square…IBM Booth #5104 • ILOG at the Java One Expo at the Hilton San Francisco Union Square….IBM Booth #5104  Meet with IBM experts at our “Solution Spotlight Sessions” in Moscone South, Booth #1111.  Access a wealth of insight including downloadable whitepapers & client successes at ibm.com/oracle. For the most current OOW updates follow us on Twitter at www.twitter.com/IBMandOracle