SlideShare a Scribd company logo
1 of 15
Java Concurrency in Practice Eric Beyeler 2009.03.19
Overview ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
WWWWWH? ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
When to use Concurrency ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Traditional Multithreading ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Java 5 Concurrency model ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
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 = 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
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
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() ); }
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
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.
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
Conclusion ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

More Related Content

What's hot

Making a Process
Making a ProcessMaking a Process
Making a ProcessDavid Evans
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopSaša Tatar
 
RedisConf17- durable_rules
RedisConf17- durable_rulesRedisConf17- durable_rules
RedisConf17- durable_rulesRedis Labs
 
Understanding Java Garbage Collection
Understanding Java Garbage CollectionUnderstanding Java Garbage Collection
Understanding Java Garbage CollectionAzul Systems Inc.
 
Introduce leo-redundant-manager
Introduce leo-redundant-managerIntroduce leo-redundant-manager
Introduce leo-redundant-managerParas Patel
 
Concurrency: Rubies, Plural
Concurrency: Rubies, PluralConcurrency: Rubies, Plural
Concurrency: Rubies, PluralEleanor McHugh
 
Concurrency: Rubies, plural
Concurrency: Rubies, pluralConcurrency: Rubies, plural
Concurrency: Rubies, pluralehuard
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core DataMatthew Morey
 
Understanding Autovacuum
Understanding AutovacuumUnderstanding Autovacuum
Understanding AutovacuumDan Robinson
 
Introduction to Twitter Storm
Introduction to Twitter StormIntroduction to Twitter Storm
Introduction to Twitter StormUwe Printz
 
A One-Stop Solution for Puppet and OpenStack
A One-Stop Solution for Puppet and OpenStackA One-Stop Solution for Puppet and OpenStack
A One-Stop Solution for Puppet and OpenStackPuppet
 
Comet with node.js and V8
Comet with node.js and V8Comet with node.js and V8
Comet with node.js and V8amix3k
 
Taking advantage of Prometheus relabeling
Taking advantage of Prometheus relabelingTaking advantage of Prometheus relabeling
Taking advantage of Prometheus relabelingJulien Pivotto
 
Putting a Fork in Fork (Linux Process and Memory Management)
Putting a Fork in Fork (Linux Process and Memory Management)Putting a Fork in Fork (Linux Process and Memory Management)
Putting a Fork in Fork (Linux Process and Memory Management)David Evans
 
T2 reading 20101126
T2 reading 20101126T2 reading 20101126
T2 reading 20101126Go Tanaka
 
Thinking in Sequences - Streams in Node.js & IO.js
Thinking in Sequences - Streams in Node.js & IO.jsThinking in Sequences - Streams in Node.js & IO.js
Thinking in Sequences - Streams in Node.js & IO.jsArtur Skowroński
 
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろうUnity Technologies Japan K.K.
 

What's hot (20)

Making a Process
Making a ProcessMaking a Process
Making a Process
 
All you need to know about the JavaScript event loop
All you need to know about the JavaScript event loopAll you need to know about the JavaScript event loop
All you need to know about the JavaScript event loop
 
RedisConf17- durable_rules
RedisConf17- durable_rulesRedisConf17- durable_rules
RedisConf17- durable_rules
 
Understanding Java Garbage Collection
Understanding Java Garbage CollectionUnderstanding Java Garbage Collection
Understanding Java Garbage Collection
 
Introduce leo-redundant-manager
Introduce leo-redundant-managerIntroduce leo-redundant-manager
Introduce leo-redundant-manager
 
Concurrency: Rubies, Plural
Concurrency: Rubies, PluralConcurrency: Rubies, Plural
Concurrency: Rubies, Plural
 
Concurrency: Rubies, plural
Concurrency: Rubies, pluralConcurrency: Rubies, plural
Concurrency: Rubies, plural
 
High Performance Core Data
High Performance Core DataHigh Performance Core Data
High Performance Core Data
 
Understanding Autovacuum
Understanding AutovacuumUnderstanding Autovacuum
Understanding Autovacuum
 
Streams in Node.js
Streams in Node.jsStreams in Node.js
Streams in Node.js
 
Introduction to Twitter Storm
Introduction to Twitter StormIntroduction to Twitter Storm
Introduction to Twitter Storm
 
A One-Stop Solution for Puppet and OpenStack
A One-Stop Solution for Puppet and OpenStackA One-Stop Solution for Puppet and OpenStack
A One-Stop Solution for Puppet and OpenStack
 
Node.js in production
Node.js in productionNode.js in production
Node.js in production
 
Comet with node.js and V8
Comet with node.js and V8Comet with node.js and V8
Comet with node.js and V8
 
Taking advantage of Prometheus relabeling
Taking advantage of Prometheus relabelingTaking advantage of Prometheus relabeling
Taking advantage of Prometheus relabeling
 
Putting a Fork in Fork (Linux Process and Memory Management)
Putting a Fork in Fork (Linux Process and Memory Management)Putting a Fork in Fork (Linux Process and Memory Management)
Putting a Fork in Fork (Linux Process and Memory Management)
 
T2 reading 20101126
T2 reading 20101126T2 reading 20101126
T2 reading 20101126
 
Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)
 
Thinking in Sequences - Streams in Node.js & IO.js
Thinking in Sequences - Streams in Node.js & IO.jsThinking in Sequences - Streams in Node.js & IO.js
Thinking in Sequences - Streams in Node.js & IO.js
 
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
【Unite 2017 Tokyo】ScriptableObjectを使ってプログラマーもアーティストも幸せになろう
 

Similar to Java Concurrency in Practice

Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stackTomáš Kypta
 
Java design patterns
Java design patternsJava design patterns
Java design patternsShawn Brito
 
.NET Multithreading/Multitasking
.NET Multithreading/Multitasking.NET Multithreading/Multitasking
.NET Multithreading/MultitaskingSasha Kravchuk
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on AndroidTomáš Kypta
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
 
От Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовОт Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовYandex
 
Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrencypriyank09
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency GotchasAlex Miller
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...DroidConTLV
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Baruch Sadogursky
 
Java concurrency
Java concurrencyJava concurrency
Java concurrencyducquoc_vn
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsChristopher Batey
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrencyfeng lee
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentJim Mlodgenski
 

Similar to Java Concurrency in Practice (20)

Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 
Modern Android app library stack
Modern Android app library stackModern Android app library stack
Modern Android app library stack
 
Java design patterns
Java design patternsJava design patterns
Java design patterns
 
.NET Multithreading/Multitasking
.NET Multithreading/Multitasking.NET Multithreading/Multitasking
.NET Multithreading/Multitasking
 
Reactive programming on Android
Reactive programming on AndroidReactive programming on Android
Reactive programming on Android
 
Fault tolerance made easy
Fault tolerance made easyFault tolerance made easy
Fault tolerance made easy
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 
Multithreading in Java
Multithreading in JavaMultithreading in Java
Multithreading in Java
 
От Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовОт Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей Родионов
 
Java 5 concurrency
Java 5 concurrencyJava 5 concurrency
Java 5 concurrency
 
Concurrency gotchas
Concurrency gotchasConcurrency gotchas
Concurrency gotchas
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
Tricks to Making a Realtime SurfaceView Actually Perform in Realtime - Maarte...
 
Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java Everything you wanted to know about writing async, concurrent http apps in java
Everything you wanted to know about writing async, concurrent http apps in java
 
Java concurrency
Java concurrencyJava concurrency
Java concurrency
 
04 threads
04 threads04 threads
04 threads
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra Applications
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrency
 
Leveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL EnvironmentLeveraging Hadoop in your PostgreSQL Environment
Leveraging Hadoop in your PostgreSQL Environment
 

Java Concurrency in Practice

  • 1. Java Concurrency in Practice Eric Beyeler 2009.03.19
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7. Chunking a large task Large Task Chunk Chunk Chunk Chunk Thread Thread Thread Thread Wait for all Main thread Continue
  • 8. Thread Pool e.g. Tomcat web server Input Stream Thread Thread Thread Thread Queue Queue Output Stream
  • 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. 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. 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. 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. 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. 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.