Java Concurrency in Practice Eric Beyeler 2009.03.19
Overview <ul><li>Concurrency – Who What When Where Why How </li></ul><ul><ul><li>CPU vs IO </li></ul></ul><ul><ul><li>Mult...
WWWWWH? <ul><li>Who? </li></ul><ul><ul><li>You! </li></ul></ul><ul><li>What? </li></ul><ul><ul><li>Executing heterogenous ...
When to use Concurrency <ul><li>Multitasking on single processor (old skool) </li></ul><ul><ul><li>I/O wait vs. CPU </li><...
Traditional Multithreading <ul><li>Threads </li></ul><ul><ul><li>Independent paths of execution </li></ul></ul><ul><ul><li...
Java 5 Concurrency model <ul><li>Memory model </li></ul><ul><ul><li>Ordering of actions </li></ul></ul><ul><ul><li>Java 4 ...
Chunking a large task Large Task Chunk Chunk Chunk Chunk Thread Thread Thread Thread Wait for all Main thread Continue
Thread Pool e.g. Tomcat web server Input Stream Thread Thread Thread Thread Queue Queue Output Stream
Executor / Callable Task Pool implementation public class ParallelWorkPool { private int taskId = 0; private int poolSize ...
Callable Task public class MyTask implements Callable<OutputData> { private InputData  inputData; private OutputData outpu...
Using the Task Pool ParallelWorkPool pool = new ParallelWorkPool(2); pool.submit( new MyTask( new InputData(3.14, 2.718) )...
Threadsafe cache class class MTCache <Resource> { public class CacheEntry { public Resource resource; public Calendar time...
Threadsafe cache class - Reloaded class MTCache <Resource> { public class CacheEntry { public Resource resource; public Ca...
Background Thread for cache cleanup class  Sweeper { public  Sweeper()  { thread =  new  SweeperThread(); } public   void ...
Conclusion <ul><li>See also: </li></ul><ul><ul><li>Java Concurrency in Practice by Brian Goetz </li></ul></ul><ul><ul><ul>...
Upcoming SlideShare
Loading in …5
×

Java Concurrency in Practice

2,554 views

Published on

  • Be the first to comment

Java Concurrency in Practice

  1. 1. Java Concurrency in Practice Eric Beyeler 2009.03.19
  2. 2. Overview <ul><li>Concurrency – Who What When Where Why How </li></ul><ul><ul><li>CPU vs IO </li></ul></ul><ul><ul><li>Multicore processors </li></ul></ul><ul><li>Traditional multithreading model </li></ul><ul><ul><li>Threads </li></ul></ul><ul><ul><li>Locks / Mutex </li></ul></ul><ul><ul><li>Producer / Consumer </li></ul></ul><ul><li>Java 5 Concurrency framework </li></ul><ul><ul><li>Tasks </li></ul></ul><ul><ul><li>Thread pools </li></ul></ul><ul><ul><li>Atomics </li></ul></ul><ul><ul><li>Lock free data structures </li></ul></ul><ul><li>Real World Examples </li></ul>
  3. 3. WWWWWH? <ul><li>Who? </li></ul><ul><ul><li>You! </li></ul></ul><ul><li>What? </li></ul><ul><ul><li>Executing heterogenous or homogenous tasks simultaneously </li></ul></ul><ul><li>When? Where? </li></ul><ul><ul><li>NOW, in a server… or laptop… near you </li></ul></ul><ul><li>- Why? </li></ul><ul><ul><li>Take advantage of modern hardware for scalability </li></ul></ul><ul><ul><li>Improve user experience </li></ul></ul><ul><li>How? </li></ul><ul><ul><li>To quote John Hammond, “I’ll show you” </li></ul></ul>
  4. 4. When to use Concurrency <ul><li>Multitasking on single processor (old skool) </li></ul><ul><ul><li>I/O wait vs. CPU </li></ul></ul><ul><ul><li>Background processing in UI </li></ul></ul><ul><li>Multicore CPUs (true parallelism) </li></ul><ul><ul><li>Large units of standalone work </li></ul></ul><ul><ul><ul><li>Processing client requests on server </li></ul></ul></ul><ul><ul><ul><li>data processing (divide into smaller independent units) </li></ul></ul></ul><ul><ul><li>I/O wait </li></ul></ul><ul><li>“ Sharing requires waiting and overhead, and is a natural enemy of scalability ” – Herb Sutter </li></ul><ul><li>The trick to effective concurrency is to do as little synchronization as possible, but no less </li></ul>
  5. 5. Traditional Multithreading <ul><li>Threads </li></ul><ul><ul><li>Independent paths of execution </li></ul></ul><ul><ul><li>Must share resources </li></ul></ul><ul><li>Locks </li></ul><ul><ul><li>Ensure atransaction is atomic </li></ul></ul><ul><li>Producer / Consumer </li></ul><ul><ul><li>Queue </li></ul></ul><ul><li>Java 4 vs Java 5 </li></ul><ul><ul><li>Double checked locking (resource creation) </li></ul></ul>
  6. 6. Java 5 Concurrency model <ul><li>Memory model </li></ul><ul><ul><li>Ordering of actions </li></ul></ul><ul><ul><li>Java 4 cannot guarantee DCLP to be correct </li></ul></ul><ul><li>java.util.concurrency </li></ul><ul><ul><li>Executor / Callable / Future framework </li></ul></ul><ul><ul><li>Lock-free data structures </li></ul></ul><ul><ul><li>AtomicInteger </li></ul></ul>
  7. 7. Chunking a large task Large Task Chunk Chunk Chunk Chunk Thread Thread Thread Thread Wait for all Main thread Continue
  8. 8. Thread Pool e.g. Tomcat web server Input Stream Thread Thread Thread Thread Queue Queue Output Stream
  9. 9. Executor / Callable Task Pool implementation public class ParallelWorkPool { private int taskId = 0; private int poolSize = 10; private final ExecutorService exec; private ExecutorCompletionService <OutputData> ecs; public ParallelWorkPool(int poolSize) { if ( poolSize > 0 ) this.poolSize = poolSize; exec = Executors.newFixedThreadPool(this.poolSize); ecs = new ExecutorCompletionService <OutputData>( exec ); } public Integer submit(MyTask task) { task.setId(++taskId); ecs.submit(task); return taskId; } public Map< Integer, OutputData > waitForAllTasks() { Map< Integer, OutputData > mapResults = new TreeMap< Integer, OutputData >(); for ( int i=0; i < taskId; i++ ) { Future<OutputData> result = ecs.take(); mapResults.put(result.get().getId(), result.get()); } return mapResults; } } // class ParallelWorkPool
  10. 10. Callable Task public class MyTask implements Callable<OutputData> { private InputData inputData; private OutputData outputData; public MyTask( InputData inputData ) { this.inputData = inputData; outputData = new OutputData(); } public void setId(int id) { outputData.setId( id ); } public int getId() { return outputData.getId(); } // this actually performs the task - inside the thread public OutputData call() { outputData.setValues( doSomething( inputData ) ); return outputData; } } // class MyTask
  11. 11. Using the Task Pool ParallelWorkPool pool = new ParallelWorkPool(2); pool.submit( new MyTask( new InputData(3.14, 2.718) ); pool.submit( new MyTask( new InputData(0, 1) ); pool.submit( new MyTask( new InputData(&quot;http://www.mapquest.com&quot;) ); pool.submit( new MyTask( new InputData(&quot;Mechanicsburg, PA&quot;) ); // wait for all tasks to complete Map<Integer, OutputData > mapResults = pool.waitForAllTasks(); for (Map.Entry<Integer,OutputData> result : mapResults.entrySet() ) { // use result.getKey() if we care about which task we have doSomething( result.getValue() ); }
  12. 12. Threadsafe cache class class MTCache <Resource> { public class CacheEntry { public Resource resource; public Calendar timeToDie; } private ConcurrentHashMap <String, CacheEntry> mapCache; private Sweeper sweeper = null; public MTCache() { mapCache = new ConcurrentHashMap <String, CacheEntry>(); } public void destroy() { sweeper.shutdown(); sweeper = null; } public void clearCache() { mapCache.clear(); } public Resource getCachedEntry(String path) { CacheEntry entry = mapCache.get(path); if ( entry != null ) return entry.resource; else return addCacheEntry( path ); } // … addCacheEntry() } // class MTCache<> private synchronized Resource addCacheEntry(String path) { Resource resource = null; CacheEntry cacheEntry = mapCache.get( path ); if ( cacheEntry != null ) resource = cacheEntry.resource; else { // OBTAIN THE RESOURCE resource = getResource(path); if ( resource != null ) { // Get current date / time Calendar timeToDie = Calendar.getInstance(); timeToDie.add(Calendar.MINUTE, imageTTLMinutes); cacheEntry = new CacheEntry(resource, timeToDie); mapCache.put( path, cacheEntry ); } } return resource; } This is an an example of the Double Checked Locking pattern
  13. 13. Threadsafe cache class - Reloaded class MTCache <Resource> { public class CacheEntry { public Resource resource; public Calendar timeToDie; } private ConcurrentHashMap <String, CacheEntry> mapCache; private Sweeper sweeper = null; public MTCache() { mapCache = new ConcurrentHashMap <String, CacheEntry>(); } public void destroy() { sweeper.shutdown(); sweeper = null; } public void clearCache() { mapCache.clear(); } public Resource getCachedEntry(String path) { CacheEntry entry = mapCache.get(path); if ( entry != null ) return entry.resource; else return addCacheEntry( path ); } // … addCacheEntry() } // class MTCache<> private Resource addCacheEntry(String path) { // OBTAIN THE RESOURCE Resource resource = getResource(path); if ( resource != null ) { // Get current date / time Calendar timeToDie = Calendar.getInstance(); timeToDie.add(Calendar.MINUTE, imageTTLMinutes); cacheEntry = new CacheEntry(resource, timeToDie); resource = mapCache. putIfAbsent ( path, cacheEntry ) .resource; } return resource; } I would favor the synchronized implementation if the resource was costly to obtain – no risk of duplicated resource creation. The “reloaded” version is better for small objects.
  14. 14. Background Thread for cache cleanup class Sweeper { public Sweeper() { thread = new SweeperThread(); } public void start() { thread.start(); } public void shutdown() { thread.killMe = true ; } SweeperThread thread; class SweeperThread extends Thread { public volatile boolean die = false ; public void run() { long i=0; while ( !die ) { TimeUnit. SECONDS .sleep(1); // check kill flag once every second if ( (++i % (60*ttlMinutes)) == 0 ) { // sweep and remove expired resources Calendar now = Calendar. getInstance (); for (Iterator<CacheEntry> it=mapCache.values().iterator(); it.hasNext();) { CacheEntry entry = it.next(); if ( now.after(entry.timeToDie) ) it.remove(); } } } // while no die flag } // run() } // class SweeperThread } // class Sweeper
  15. 15. Conclusion <ul><li>See also: </li></ul><ul><ul><li>Java Concurrency in Practice by Brian Goetz </li></ul></ul><ul><ul><ul><li>Can print out sample chapter from website </li></ul></ul></ul><ul><ul><li>A Fundamental Turn Toward Concurrency in Software </li></ul></ul><ul><ul><ul><li>http://www.ddj.com/architect/184405990 By Herb Sutter ( http:// gotw.ca ) </li></ul></ul></ul><ul><li>Questions? </li></ul>

×