MONTREAL 1/3 JULY 2011Concurrency and Thread-Safe DataProcessing in Background TasksKieran KelleherGreen Island Consulting...
Why Background Threads?•   “Background” = Not in the Request-Response thread (WOWorkerThread)    •   We can execute long-r...
Objectives•   How to run simple background tasks with the least effort on your behalf.•   Start an asynchronous task•   Us...
Anatomy of a “Task”public class SimpleRunnable implements Runnable {	    public void run() {	    	    //Do a whole lot of ...
Executing a Task•   Use java.util.concurrent.*    •   Convenient, easy to use.•   In summary: Basic concurrency classes to...
Executing a Task// Creating an ExecutorService in plain JavaExecutorService executorService = Executors.newCachedThreadPoo...
Demo 1
ERXExecutorService                               creates a             ERXTaskThreadPoolExecutor              returns     ...
Benefits of using ExecutorService instances              returned by ERXExecutorService•   Allows for loosely coupled plain...
The “Ideal” Long Response Page?•   Provides feedback to the user•   Simple UI and easy to understand user experience•   Ca...
Demo 2
CCAjaxLongResponsePage• Resides in ERCoolComponents framework• Easy to use ... really!• CSS styleable• Customizable via Pr...
CCAjaxLongResponsePage// Basic usage: run a task in long response page and return to the same page	    public WOActionResu...
Monitoring & Controlling Tasks•   ERXStatusInterface    •   public String status();•   ERXTaskPercentComplete    •   publi...
Demo 3
EOF Background Tasks•   Good Practices    •   Only pass EOGlobalIDs (or raw rows) between threads    •   Manual lock/unloc...
FYI, About the Demo EOModel                (Number Crunching for the sake of it)                                          ...
Demo 4
How It Works      Originating Page                                   CCAjaxLongResponsePage            Callable           ...
IERXPerformWOActionForResult•   Interface    •   public WOActionResults performAction();    •   public void setResult(Obje...
Customize end of task WOActionResults behavior	   // Example of action in originating page to return a long response page ...
Avoiding the default EOObjectStoreCoordinator                                     in your task// Using an OSC from a pool ...
Handling the return object// If you implement your own IERXPerformWOActionForResult and result is an EOGlobalIDif (_result...
Multi-threaded Tasks                   Task (Manager)         Fixed size private ExecutorServiceChildChild      Child     ...
Demo 5
Multi-threaded task notes•   Parent task can delegate batches of work to child tasks    •   Concept - many child tasks ser...
Working with Fixed Thread Pool ExecutorServiceExecutorService es = ERXExecutorService.newFiniteThreadPool(4);boolean isRej...
Passing Parameters to a Task    private final EOGlobalID _myObjectID     // Example Task Constructor	   public MyUpdateTas...
Problems and Solutions (1/2)•   Memory when Processing Huge Data Sets    •   Allocate More Memory    •   Force garbage col...
Problems and Solutions (2/2)•   Prevent bottleneck in default EOObjectStoreCoordinator    •   ERXTaskObjectStoreCoordinato...
More Information•   Demo App: wonder/Examples/Misc/BackgroundTasks•   Java API Docs    •   Runnable, Callable, ExecutorSer...
MONTREAL 1/3 JULY 2011Q&AConcurrency and Thread-Safe Data Processing in Background TasksKieran Kelleher
Upcoming SlideShare
Loading in...5
×

Concurrency and Thread-Safe Data Processing in Background Tasks

1,483

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,483
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
35
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Concurrency and Thread-Safe Data Processing in Background Tasks

  1. 1. MONTREAL 1/3 JULY 2011Concurrency and Thread-Safe DataProcessing in Background TasksKieran KelleherGreen Island Consulting LLCSmartleadsUSA LLCSmartMix Technologies LLC
  2. 2. Why Background Threads?• “Background” = Not in the Request-Response thread (WOWorkerThread) • We can execute long-running logic asynchronously in a background thread.• An action MAY be always or sometimes too long • Examples • importing a mailing list of 50 records versus a list of 100,000 records. • Generating a report off a selection of 50 EOs versus 100,000 EOs. • your app interacting with remote web services (connection timeouts, etc.) • interacting with a merchant payment gateway (Credit Card processing) • Administration & Bulk Data Processing Operations
  3. 3. Objectives• How to run simple background tasks with the least effort on your behalf.• Start an asynchronous task• Use a long response page to start a task, monitor and handle a task result • with basic user feedback (busy) • with better user feedback (progress, status)• How to work with EOF in the context of background threads.• How to pass arguments and return results (including EOs) from asynchronous tasks.• How to run a multi-threaded bulk data processing asynchronous task to get more done faster.• Introduce convenient classes in Wonder that are related to running tasks in background threads.
  4. 4. Anatomy of a “Task”public class SimpleRunnable implements Runnable { public void run() { //Do a whole lot of stuff here }}public class SimpleCallable implements Callable<ResultType> { public ResultType call() { //Do a whole lot of stuff here return _someResult; }}
  5. 5. Executing a Task• Use java.util.concurrent.* • Convenient, easy to use.• In summary: Basic concurrency classes to understand • Runnable, Callable, ExecutorService, Future• java.util.concurrent.ExecutorService interface • executorService.execute( task ); • Future future = executorService.submit( task );• java.util.concurrent.Future interface • future.get() or future.get(timeout, timeUnit) • future.isDone()
  6. 6. Executing a Task// Creating an ExecutorService in plain JavaExecutorService executorService = Executors.newCachedThreadPool();// Getting a reference to the WebObjects-friendly singleton ExecutorServiceExecutorService executorService = ERXExecutorService.executorService()// Starting an asynchronous task (aka run it in another thread)Runnable task = new MyRunnableTask();executorService.execute( task );// Starting an asynchronous task and keeping an eye on itFuture future = executorService.submit( task );// Starting a task in a WebObjects actionpublic WOActionResults dispatchBackgroundTask() { MyTask task = new MyTask(); ERXExecutorService.executorService().execute(task); return null;}
  7. 7. Demo 1
  8. 8. ERXExecutorService creates a ERXTaskThreadPoolExecutor returns ERXFutureTaskERXExecutorService extends ThreadPoolExecutor implements Future implements ExecutorService (utility class) has a ERXThreadFactory implements ThreadFactory• Usage creates • ExecutorService es = ERXExecutorService.executorService(); ERXTaskThread • es.execute( runnable ); extends Thread • Future future = es.submit( task ); • You generally don’t need to directly use the stuff to the right :-)
  9. 9. Benefits of using ExecutorService instances returned by ERXExecutorService• Allows for loosely coupled plain Runnable and Callable tasks. • No subclassing necessary to get WO integration!• EC Safety Net: Automatically unlocks all EC’s at the end of task execution (no subclassing needed) • NOT a reason to ignore locking!• TODO: ERXThreadStorage “safe” cloning.• By the way... • ERXTaskThread subclass of Thread used • supports use of ERXExecutionStateTransition interface in your task.
  10. 10. The “Ideal” Long Response Page?• Provides feedback to the user• Simple UI and easy to understand user experience• Can be reusable and easy (even pleasant) to implement • ! WOLongResponsePage• Controls the user by making them wait • May not be a good idea for very long tasks
  11. 11. Demo 2
  12. 12. CCAjaxLongResponsePage• Resides in ERCoolComponents framework• Easy to use ... really!• CSS styleable• Customizable via Properties
  13. 13. CCAjaxLongResponsePage// Basic usage: run a task in long response page and return to the same page public WOActionResults dispatchBackgroundTaskInLongResponsePage() { Runnable task = new MyRunnableTask(); CCAjaxLongResponsePage nextPage = pageWithName(CCAjaxLongResponsePage.class); nextPage.setTask(task); return nextPage; }###################################################################### Optional configuration properties###################################################################### A default status message to display if the long running task does not implement ERXStatusInterfaceer.coolcomponents.CCAjaxLongResponsePage.defaultStatus=Please wait...# Stylesheet for CCAjaxLongResponsePageer.coolcomponents.CCAjaxLongResponsePage.stylesheet.framework = ERCoolComponentser.coolcomponents.CCAjaxLongResponsePage.stylesheet.filename = CCAjaxLongResponsePage.css# Useful for developing a custom CSS style-sheet. When set to true, this flag prevents AJAX refresh on all containers# on the CCAjaxLongResponsePage and keeps the page open indefinitely even after the task has completed.er.coolcomponents.CCAjaxLongResponsePage.stayOnLongResponsePageIndefinitely = false# Default refresh interval for CCAjaxLongResponsePage#er.coolcomponents.CCAjaxLongResponsePage.refreshInterval = 2#Defines a default controller class, other than the hard-coded default, for handling task errors for the applicationer.coolcomponents.CCAjaxLongResponsePage.nextPageForErrorResultControllerClassName=com.myproject.MyErrorController
  14. 14. Monitoring & Controlling Tasks• ERXStatusInterface • public String status();• ERXTaskPercentComplete • public Double percentComplete();• IERXStoppable • public void stop();• Only ONE method in each interface!! :-)
  15. 15. Demo 3
  16. 16. EOF Background Tasks• Good Practices • Only pass EOGlobalIDs (or raw rows) between threads • Manual lock/unlock. --- EC lock() / try / finally / unlock() • Avoid using default EOObjectStoreCoordinator• Things to remember • Task constructor code does not run in the task thread. • Pass in an EO in constructor - convert to EOGlobalID
  17. 17. FYI, About the Demo EOModel (Number Crunching for the sake of it) ResultItem ResultItem TaskInfo ResultItem ResultItem Entity ResultItem ResultItem EntityRepresents a single Represents result of one loop iteration.execution of a task 1) Checking if a number if Prime 2) Checking if a Prime is a Factorial Prime
  18. 18. Demo 4
  19. 19. How It Works Originating Page CCAjaxLongResponsePage Callable nextPage.setTask(..) CallableIERXPerformWOActionForResult nextPage.setNextPageForResultController(..) IERXPerformWOActionForResult Result Page
  20. 20. IERXPerformWOActionForResult• Interface • public WOActionResults performAction(); • public void setResult(Object result);• Utility Implementation • ERXNextPageForResultWOAction • new ERXNextPageForResultWOAction(resultPage, "resultKey");
  21. 21. Customize end of task WOActionResults behavior // Example of action in originating page to return a long response page public WOActionResults performTaskWithCustomResultController() { // Create the controller for handling the result and returning the next page after the task is done IERXPerformWOActionForResult controller = new ERXNextPageForResultWOAction(pageWithName(MyResultPage.class), "resultKeyInPage"); // Create the task Callable<EOGlobalID> task = new MyCallableTask(); // Create the CCAjaxLongResponsePage instance CCAjaxLongResponsePage nextPage = pageWithName(CCAjaxLongResponsePage.class); // Push controller and the task into CCAjaxLongResponsePage nextPage.setNextPageForResultController(controller); nextPage.setTask(task); // Return the CCAjaxLongResponsePage instance return nextPage; }
  22. 22. Avoiding the default EOObjectStoreCoordinator in your task// Using an OSC from a pool of OSC dedicated to background tasks. Pool size configurable.EOObjectStoreCoordinator osc = ERXTaskObjectStoreCoordinatorPool.objectStoreCoordinator();EOEditingContext ec = ERXEC.newEditingContext( osc );ec.lock();try { // Do stuff} finally { ec.unlock();}# Configure the default OSC pool size for background tasks with propertyer.extensions.concurrency.ERXTaskObjectStoreCoordinatorPool.maxCoordinators = 4// Convenience class ERXAbstractTask// @see ERXAbstractTask#newEditingContext()public class MyRunnable extends ERXAbstractTaskJust extend ERXAbstractTask and call newEditingContext() !
  23. 23. Handling the return object// If you implement your own IERXPerformWOActionForResult and result is an EOGlobalIDif (_result instanceof EOGlobalID) { // Create a new EC EOEditingContext ec = ERXEC.newEditingContext(); // Lets ensure fresh ec since we are likely coming out of a background task ec.setFetchTimestamp(System.currentTimeMillis()); _result = ec.faultForGlobalID((EOGlobalID) _result, ec); }_nextPage.takeValueForKey(_result, _nextPageResultKey);
  24. 24. Multi-threaded Tasks Task (Manager) Fixed size private ExecutorServiceChildChild Child Child Child Child Child ChildChild Child Child Child
  25. 25. Demo 5
  26. 26. Multi-threaded task notes• Parent task can delegate batches of work to child tasks • Concept - many child tasks serviced by finite thread count ExecutorService• Use EOGlobalIDs (or raw rows) as parameters to the child tasks. • DO NOT pass EOs directly to child tasks.• Fixed thread pool • static var: pool is shared between all instances of the task (resource conservative) • instance var: pool is dedicated to each task (careful)• Take care to correctly size the ERXTaskObjectStoreCoordinatorPool • er.extensions.concurrency.ERXTaskObjectStoreCoordinatorPool.maxCoordinators = n• Use Futures to track child task completion. Don’t exit until all child tasks have completed.
  27. 27. Working with Fixed Thread Pool ExecutorServiceExecutorService es = ERXExecutorService.newFiniteThreadPool(4);boolean isRejected = true;while ( isRejected ) { try { Future<?> future = es.submit(childTask); } catch (RejectedExecutionException e) { try { Thread.sleep(2000); } catch (InterruptedException e1) { // Handle that } }}
  28. 28. Passing Parameters to a Task private final EOGlobalID _myObjectID // Example Task Constructor public MyUpdateTask(MyEntityClass eo) { if (eo.isNewObject()) { throw new IllegalArgumentException("MyEntityClass cannot be a new unsaved object"); } // Grab GID reference before the task is started. _myObjectID = eo.editingContext().globalIDForObject(eo); }
  29. 29. Problems and Solutions (1/2)• Memory when Processing Huge Data Sets • Allocate More Memory • Force garbage collection (for example if above a % usage) • Recycle EOEditingContexts periodically (see demo T06xxx.java)• Large toMany Relationships • Remove the toMany from the EOModel and use ERXUnmodeledToManyRelationship • @see example usage in ‘BackgroundTasks’ demo: • TaskInfo.resultItems relationship.
  30. 30. Problems and Solutions (2/2)• Prevent bottleneck in default EOObjectStoreCoordinator • ERXTaskObjectStoreCoordinatorPool.objectStoreCoordinator() • er.extensions.concurrency.ERXTaskObjectStoreCoordinatorPool.maxCoordinators = n • Implement IERXRefreshPage interface on result page to prevent stale EO result. • in refresh() call ERXEOControlUtilities.refreshObject( eo ); • @see demo TaskInfoPage and logic in ERXNextPageForResultController• Use Fresh Data in your background tasks • ec.setFetchTimestamp(System.currentTimeMillis()); • ERXEOControlUtilities.refreshObject( eo );
  31. 31. More Information• Demo App: wonder/Examples/Misc/BackgroundTasks• Java API Docs • Runnable, Callable, ExecutorService, Future, Executors• Wonder classes and javadoc • CCAjaxLongResponsePage • IERXPerformWOActionForResult / ERXNextPageForResultWOAction, IERXRefreshPage • ERXStatusInterface, ERXTaskPercentComplete, IERXStoppable • ERXExecutorService • ERXAbstractTask, ERXTaskObjectStoreCoordinatorPool• Effective Java, 2nd Edition by Joshua Bloch, chapter 10
  32. 32. MONTREAL 1/3 JULY 2011Q&AConcurrency and Thread-Safe Data Processing in Background TasksKieran Kelleher
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×