Con Currency
Con Currency
java.util.concurrency and multithreading
1) Problems using hashmap in a multithreaded app.
2) Using a concurrent hashmap
3) Catching exceptions from threads
4) Using Executor in java.util.concurrency
4.1) Single thread executor
4.2) Thread Per Task executor
4.3)Executors.newFixedThreadPool
4.3)Executors.newCachedThreadPool
1) Problems using HashMap
Creates 20 threads that put strings into a shared hashmap.
In the main thread concurrently iterate over the hashmap
public class Hash {
HashMap<String, String> chm =
new HashMap<String, String>(16);
public Hash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
new Thread(
new Runner(chm,"t"+i,50)).start();
}
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread: Key:" + key+
" and value:" + chm.get(key) );
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
}
…
MainThread: Key:Thread-0-21 and value:t0
MainThread: Key:Thread-2-13 and value:t2
MainThread: Key:Thread-5-35 and value:t5
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:841)
at java.util.HashMap$KeyIterator.next(HashMap.java:877)
at javait.concurrent.Hash.<init>(Hash.java:23)
at javait.concurrent.Hash.main(Hash.java:12)
2) Using concurrent Hashmap
Modify the above example to use a ConcurrentHashmap.
package javait.concurrent;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
/*
* Things to try:
* Read the api and modify the number from concurrencyLevel to suggest alternative
* sizing for partitioning
* change the number of threads and iterations.
*/
public class ConHash {
public ConHash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
new Thread(new Runner(chm,"t"+i,50)).start();
}
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread read Key:" + key
+ " and value:" + chm.get(key) );
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
}
class Runner implements Runnable{
ConcurrentHashMap<String , String> hm = null;
int count;
String message;
…
MainThread read Key:Thread-7-18 and value:t7
MainThread read Key:Thread-7-28 and value:t7
MainThread read Key:Thread-7-17 and value:t7
MainThread read Key:Thread-7-39 and value:t7
MainThread read Key:Thread-7-30 and value:t7
MainThread read Key:Thread-7-23 and value:t7
MainThread read Key:Thread-7-45 and value:t7
MainThread read Key:Thread-7-42 and value:t7
MainThread read Key:Thread-7-38 and value:t7
MainThread read Key:Thread-7-16 and value:t7
MainThread read Key:Thread-7-33 and value:t7
MainThread read Key:Thread-7-48 and value:t7
MainThread read Key:Thread-7-31 and value:t7
MainThread read Key:Thread-7-26 and value:t7
MainThread read Key:Thread-7-11 and value:t7
MainThread read Key:Thread-7-36 and value:t7
MainThread read Key:Thread-7-19 and value:t7
MainThread read Key:Thread-7-25 and value:t7
MainThread read Key:Thread-7-14 and value:t7
MainThread read Key:Thread-7-47 and value:t7
MainThread read Key:Thread-7-40 and value:t7
Time Taken is:78
3) Catching exceptions from threads
static {
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e){
System.err.println(
"Thread caught by default handler="+ t.getName());
e.printStackTrace();
}
});
}
}
4) Using Executor in java.util.concurrency
4.1) Single thread executor
import java.util.*;
import java.util.concurrent.*;
public SingleExecuteHash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
threadExecutor.execute(new Runner(chm,"t"+i,50)); // no
start()!!!
}
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread read Key:" + key+
" and value:" + chm.get(key) );
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
}
package javait.concurrent;
import java.util.*;
import java.util.concurrent.*;
public ThreadPerTaskExecuteHash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
threadExecutor.execute(new Runner(chm,"t"+i,50)); }
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread read Key:" + key+
" and value:" + chm.get(key) );
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
}
/*
* Shows threads from a pool being reused!!!
*/
public class CachePoolExecuteHash {
public CachePoolExecuteHash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
execservice.execute(new Runner(chm,"t"+i,50
}
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread read Key:" + key+
" and value:" + chm.get(key) );
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
…
MainThread read Key:pool-1-thread-4-23 and value:t19
MainThread read Key:pool-1-thread-4-0 and value:t19
…
MainThread read Key:pool-1-thread-4-32 and value:t19
MainThread read Key:pool-1-thread-4-42 and value:t19
MainThread read Key:pool-1-thread-4-15 and value:t19
…
MainThread read Key:pool-1-thread-1-2 and value:t6
MainThread read Key:pool-1-thread-4-21 and value:t19
…
MainThread read Key:pool-1-thread-1-8 and value:t6
MainThread read Key:pool-1-thread-4-38 and value:t19
…
MainThread read Key:pool-1-thread-5-22 and value:t4
MainThread read Key:pool-1-thread-5-44 and value:t4
MainThread read Key:pool-1-thread-5-14 and value:t4
Time Taken is:38
4.3)Executors.newCachedThreadPool
java.util.concurrent.Executors.newCachedThreadPool()
Creates a thread pool that creates new threads as needed, but will reuse previously
constructed threads when they are available. These pools will typically improve the
performance of programs that execute many short-lived asynchronous tasks. Calls to
execute will reuse previously constructed threads if available. If no existing thread is
available, a new thread will be created and added to the pool. Threads that have not been
used for sixty seconds are terminated and removed from the cache. Thus, a pool that
remains idle for long enough will not consume any resources. Note that pools with similar
properties but different details (for example, timeout parameters) may be created using
ThreadPoolExecutor constructors.
public CachePoolExecuteHash(){
long start= System.currentTimeMillis();
for (int i= 0; i <20; ++i){
execservice.execute(new Runner(chm,"t"+i,50));
}
Iterator<String > keys= chm.keySet().iterator();
while(keys.hasNext()){
String key=keys.next();
System.out.println("MainThread read Key:" + key+
" and value:" + chm.get(key));
}
long stop=System.currentTimeMillis();
long timeTaken = stop-start;
System.out.println("Time Taken is:"+ timeTaken);
}
}