Home » Core Java » Java Concurrency in Practice

Java Concurrency in Practice

Concurrent programming covers concept of parallel program execution, inter process or thread communication, shared object , thread executor frame work, future and callable objects etc.

In this article we would cover following concepts :

  1. What is concurrency
  2. Process and Threads
  3. Thread communication
  4. Synchronization and Locking
  5. Atomic variable, Volatile variable and Semaphores
  6. Immutable objects
  7. High level of concurrency
  8. Executor framework
  9. Future and Callable objects
  10. Concurrent Collection

1: What is Concurrency: Concurrency means ability to run various part of a program parallely. Classic example is your mobile phone where you can talk while while accessing net and your phone pops out any live notifications without waiting any process to complete. So in other words these set of process are running parallel and this is called concurrency.

Java Provides set of APIs to write concurrent programming application that we would cover in this article.

2: Process and Threads: Java Process are same as any other operating system process, they have their own memory allocation and own set of resources. This is a simple example to show how can you create a process using Java API to invoke any OS level command.


public static void main(String[] args){
		try {
			Process p = new ProcessBuilder("ls", "-l").start();
			BufferedInputStream bin = new BufferedInputStream(p.getInputStream());
			InputStreamReader inReader = new InputStreamReader(bin);
			BufferedReader reader = new BufferedReader(inReader);
			String line;
			while((line = reader.readLine())!=null){
				System.out.println(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

Threads on the other hand are light weight processes which are created from a single parent process. Threads can share all resources belong to its parent thread or process and they occupy less memory with respect to the process.

Java API provides two ways to create threads

  • Implementing Runnable Interface
  • Extending Thread Class

We all know about them so I am not going in deep of them.

3: Thread Communication: Thread communication means all possible ways by which threads can send signals to each other and do some work in specified or synchronized manner. For example suppose there are some Producers and Consumers for some goods for a particular Store. So here Producer can produce so item only if store is not FULL otherwise Producer would wait till Consumer consumes some of the products . Same way for Consumer they can consume only if  that Store is not empty or else they would have to wait till a Producer produces some products.

Some common ways of thread communications are described here:

-Thread.sleep(milliseconds) This way is not very efficient but still a possible way where you put a Thread in sleep based on some condition. This would invoke the thread after specified time and check again if the condition is satisfied or not.    ex:   if(condition) then Thread.sleep(millisecond);

-Wait/Notify/Notify All: A Thread  can invoke Object.wait() method if any condition is not satisfied and this would put that thread in wait condition. When some other Second thread invokes Notify or Notify All then previous thread/s would be notified, here this second thread might change the conditional state which would enable previous thread to resume their execution once they are notified.

-CountDownLatch/CyclicBarrier: A Synchronization technique which allows one or more thread to wait until some specified no of tasks are performed by another thread.

CountDownLatch signal = new CountDownLatch(N);

CountDownLatch is initialized with some counter value. A thread which invokes signal.await(); get blocks until current count reaches zero by some other thread by calling signal.countDown()

-Semaphore: It also little bit similar concept as CountDownLatch but rather storing any counter value a semaphore maintain set of permits (like tokens). A thread has to acquire a permit before executing some exclusive section and after its execution is complete it has to release the permit. This approach is useful in cases where there are fixed no of worker threads has to work on a task.

Semaphore available = new Semaphore(MAX_AVAILABLE, true);

A semaphore which is initialized with value one can serve for mutual exclusion execution where at a time only one thread can enter the execution after accruing the required permit from semaphore.

4: Synchronization and Locking : When multiple thread are accessing a shared resource then in order to maintain its data integrity it is necessary that at a time only one thread is accessing or updating the resource. There are two ways of basic synchronization which are  achieved with the help of intrinsic Lock associated an Object.

Method Synchronization: We can make whole method synchronized and the running thread would take lock on the object which owns that method.

public synchronized int getCounter (int value) {
//method code
}

Synchronized Block : If we don’t want to make whole method as synchronized then we can put the set of statements in synchronized block which we want to be executed by single thread a time. Not to mention that we should prefer synchronized block over method as they reduces size of synchronized code. Unnecessary synchronized code is always a processing overhead so keep it minimal.

synchronized(Object) {
// statements to be synchronized
}

5: Atomic variable, Volatile variable and Semaphores: 

Atomic variables:  Java has provided set of classes in java.util.concurrent.atomic package, these classes have get and set methods which works like reading and writing on Volatile variables. Basically they ensure that all update operations should work in atomic manner even if they are not put in manual synchronized.

Volatile variable: If a thread access some variable usually they keep them in their local cache. But if want to enforce that thread should always read that variable from main memory whenever they access then we can mark it as volatile.

private volatile int counter;

Java 5 guarantees that write(update) to any volatile variable happens before any concurrent read. This becomes very important where all reader threads do not acquire any locking and until writer thread comes out of the synchronization block they can still use old value.  Note: Volatile can not be used with classes or methods so they are not the replacement of synchronized section.

Semaphore: It also little bit similar concept as CountDownLatch but rather storing any counter value a semaphore maintain set of permits (like tokens). A thread has to acquire a permit before executing some exclusive section and after that it has to release the permit. We have explained in detail in Inter Thread Communication Section.

6: Immutable objects: In some cases we my not want to allow to change the state of the object once it created example String class is immutable class. Immutable objects can not be modified so they are automatically thread safe in con current execution.

Read more about immutable class in my another section :Guidelines to write immutable classes.

=====================================================================================

7: High level of concurrency: Java 5 onward version has very good built in APIs to support advance level of concurrency. High level concurrency provides following components :

-Locks: java.util.concurrent.locks.*  package. So far we have used Java implicit lock which is simple to use but has some limitations. Java concurrent Locking API provides more versatile Lock interface and its implementations ReadWriteLock , RenterantLock which also works like implicit Object Lock. We would cover it in detail in my another article. Here is small code to using Lock Api.


       //Creating Lock object 
       private final Lock lock = new ReentrantLock();
       Boolean myLock = false;
       //accruing the lock
       myLock = lock.tryLock();
       //releasing the lock
       lock.unlock();

-Executors:  So far Threads were sufficient for simple applications for concurrent programming. In highly complex and lag application it is difficult and complex to do thread management by ourselves. Java API 5 onward has built in framework  to create , maintain the set of threads and their life cycle. Our job is to provide them a Runnable worker Object for business processing.

Executor Interface: java.util.concurrent package has defined three executor interfaces. Executor provides simple method e.execute() which is equivalent to new Thread(runnable).start() call.

1:Executor interface support launching of new tasks by its execute method.

2:ExeutorService, sub interface of executor which can manage life cycle of both task and executor. It supplements execute method with similar submit method: <T> Future submit(Runnable task, T result). Here return types Futures object’t get method would return the result on successful execution.

3:ScheduledExecutor is sub interface of ExecutorService which additionally allows to run a callable or runnable object after specified delay or periodically.

ThreadPool: Most of the executor implementation use ThreadPool which consist of number of worker thread which can execute a runnable task. This reduces the overhead of thread creation and thread life cycle management in large application.

Example:

 
         public static void main(String[] args) {
          //Specify a RejectedExecutionHandler to handle the task in case they are rejected by thread pool when Queue is also fulled.
          RejectedExecutionHandler rejHandler = new PoolRejectHandler();
          // specify default size of ThreadPool
          int coreSize=10;
          // specify maximum size of Thread Pool
          int maxSize = 50;
          int keepAliveTime = 900;
          // specify the Queue to hold runnable objects while no of threads exceeds to Default Pool Size
          BlockingQueue queue = new LinkedBlockingDeque(200);
          ThreadPoolExecutor pool = new ThreadPoolExecutor(coreSize, maxSize, keepAliveTime, TimeUnit.MILLISECONDS,
 queue, rejHandler);
          Runnable worker = new Worker();
          //execute the runnable task
          pool.execute(worker);
          }

-Future and Callable Objects: Future Interface represents the result of an asynchronous call. It provides methods to check if the computation is complete, to wait for its completion or to retrieve the result of the computation. This is the object which is return by the ExecutorService submit method, it can be used for doing post processing once thread’s execution is over.

Callable:A task that returns a result and may throw an exception. Implements define a single method with no arguments called call. This is a supplement to Runnable and can be passed in Executor.submit() method.

10: Concurrent Collections: JAVA API has given several ready to use concurrent collection in java.util.concuttent package. These collections can be categorized by thee main interface they implement .

BlockingQueue: It is sub interface of Queue and in addition it provides get() and put() . get() method would wait of the queue is empty and put method would wait if the queue is full. Hence no need to put additional monitors wile working with multiple threads. LinkedBloackingQueue and ArrayBlocking Queue are popular implementation of this.

ConcurrentMAP: This is sub interface of java.util.Map, that defines useful Atomic operation. That means remove or replace key value only if key-value is present or add key-value only if key is absent. Making these operations atomic in nature helps to avoid need of synchronization.   Popular implementation of ConcurrentMap is Concurrent HashMap.

-ConcurrentNavigableMap: This is third interface provided in Concurrent package how ever this is not very much popular as above two interfaces. This supports approximate match and its popular implementation is ConcurrentSkipListMap

 

Advertisements

3 Comments

  1. kevin says:

    That’s a great article with good stuff in java collection api. I found you have well written about high level of concurrency..
    Thanks man.good luck.

  2. Snehal Rastogi says:

    thank you Manjul , it was very good article about Java Concurrency.

  3. Snehal Rastogi says:

    Good description about Atomic variable and Future Objects

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: