Monday, 29 February 2016

Initializer block in Java

If you want to initialize an instance variable you will put that code in a constructor. There is one alternative to using a constructor to initialize instance variables which is called initializer block.

Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword.

General form of Initializer block

{
    // whatever code is needed for initialization goes here
}

Usage

The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors. Common code, that is used by all the constructors can be put in the initializer block.

Example code

public class InitBlockDemo {
 // no-arg constructor
 InitBlockDemo(){
  System.out.println("no-arg constructor invoked");
 }
 // constructor with one param
 InitBlockDemo(int i){
  System.out.println("constructor with one param invoked");
 }
 // initializer block
 {
  System.out.println("This will be invoked for all constructors");
 }
 public static void main(String[] args) {
  InitBlockDemo ibDemo = new InitBlockDemo();
  InitBlockDemo ibDemo1 = new InitBlockDemo(10);

 }
}

Output

This will be invoked for all constructors
no-arg constructor invoked
This will be invoked for all constructors
constructor with one param invoked

Here it can be seen that the code with in the initializer block is copied in every constructor and that code is executed when the constructor of the class is called.

That's all for this topic Initializer block in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. static block in Java
  2. Constructor chaining in Java
  3. Constructor in Java
  4. Constructor overloading in Java
  5. Core Java basics interview questions

You may also like -

>>>Go to Java Basics page

Friday, 26 February 2016

static block in Java

Static block is used for static initializations of a class. Consider the scenario when initialization of static variables requires some logic (for example, error handling or a for loop to fill a complex array). In such scenarios, simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.

A static block in a class is executed only once, when the class is first loaded, even before the main method. Note that class can be loaded when you make an object of that class or when you access the static member of that class for the first time.

General form of the static block

static{
// whatever code is needed for initialization goes here
}

Example code

public class StaticBlockDemo {
  // static blank final variable
  static final int i;
  static int b;
  //static block
  static {
   System.out.println("in static block");
   i = 5;
   b = i * 5;
   System.out.println("Values " + i + " " +  b);
  }
  
  public static void main(String[] args) {
  System.out.println(" in main method ");

  }
}

Output of the program

in static block
Values 5 25
in main method

It can be seen that main method is called only after executing the static block. In static block the static blank final variable is initialized. Also another static variable too is initialized with in the block after some computation.

A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

Since static blocks are used to initialize the class variables so static blocks are called before the constructor of the class.

public class StaticBlockDemo {
  // static blank final variable
  static final int i;
  static int b;
  //static block
  static {
   System.out.println("in static block");
   i = 5;
   b = i * 5;
   System.out.println("Values " + i + " " +  b);
  }
  
  StaticBlockDemo(){
   System.out.println("In constructor");
  }
  
  public static void main(String[] args) {
  System.out.println("in main method ");
  StaticBlockDemo sb = new StaticBlockDemo();

  }
  
  static {
   System.out.println("In another static block");
  }

}

Output

in static block
Values 5 25
In another static block
in main method 
In constructor

throw from a static block

static block can throw only RunTimeException, or there should be a try-catch block to catch checked exception.

Example Code

static int i;
static int b;
static {
 System.out.println("in static block");
 try{
  i = 5;
  b = i * 5;
 }catch(Exception exp){
  System.out.println("Exception while initializing" + exp.getMessage());
  throw new RuntimeException(exp.getMessage()); 
}
 //System.out.println("Values " + i + " " +  b);
}

That's all for this topic static block in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. static in Java
  2. static method overloading or overriding in Java
  3. static import in Java
  4. Why main method static in Java
  5. interface static methods in Java 8
  6. Initializer block in Java

You may also like -

>>>Go to Java Basics page

Thursday, 25 February 2016

Different bean scopes in Spring

When you create a bean definition, you provide a configuration for creating actual instances of the class defined by that bean definition.

By providing bean definition you can control not only, the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition, but also the scope of the objects created from a particular bean definition.

Beans can be defined to be deployed in one of a number of scopes: out of the box, the Spring Framework supports six scopes -

Scope Description

  1. singleton - Scopes a single bean definition to a single object instance per Spring IoC container. This is the default scope in Spring which means if you don't provide any scope Spring will conider the bean to have singleton scope.
  2. prototype - Scopes a single bean definition to any number of object instances.
  3. request - Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
  4. session - Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
  5. global session - Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext.
  6. application - Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.

Singleton Scope

If you define a bean definition and it is scoped as a singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object.

The singleton scope is the default scope in Spring. To define a bean as a singleton in XML, you would write, for example:

<bean id="accountService" class="com.foo.DefaultAccountService"/>

<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>

The prototype scope

When you define a bean and provide prototype scope that results in the creation of a new bean instance every time a request for that specific bean is made.

The following example defines a bean as a prototype in XML:

<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>

Note that Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called.

Request scope

If a bean is defined with scope as request, it means Spring container creates a new instance of that bean by using the bean definition for each and every HTTP request.

<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>

When the request completes processing, the bean that is scoped to the request is discarded.

Session Scope

If a bean is defined with scope as session the Spring container creates a new instance of the that bean by using the bean definition for the lifetime of a single HTTP Session. So the created bean instance is effectively scoped at the HTTP Session level.

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session is also discarded.

Global session scope

The global session scope is similar to the standard HTTP Session scope and applies only in the context of portlet-based web applications. The portlet specification defines the notion of a global Session that is shared among all portlets that make up a single portlet web application.

Beans defined at the global session scope are scoped (or bound) to the lifetime of the global portlet Session.

If you write a standard Servlet-based web application and you define one or more beans as having global session scope, the standard HTTP Session scope is used, and no error is raised.

<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>

Application scope

If a bean is defined with the scope as application, then the Spring container creates a new instance of the bean by using that bean's definition once for the entire web application.

<bean id="appPreferences" class="com.foo.AppPreferences" scope="application"/>

The bean is scoped at the ServletContext level, stored as a regular ServletContext attribute.

Note that the request, session, and global session scopes are only available if you use a web-aware Spring ApplicationContext implementation (such as XmlWebApplicationContext). If you use these scopes with regular Spring IoC containers such as the ClassPathXmlApplicationContext, you get an IllegalStateException complaining about an unknown bean scope.

That's all for this topic Different bean scopes in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What is Dependency Injection in Spring
  2. Bean definition inheritance in Spring
  3. Spring example program using JavaConfig and Annotations
  4. How to inject prototype scoped bean in singleton bean
  5. Creating a Maven project in Eclipse

You may also like -

>>>Go to Spring tutorial page

Tuesday, 23 February 2016

Injecting prototype bean in singleton bean in Spring

If we go by the definition of the singleton and prototype beans, it says -

  • Singleton scope - Only one shared instance of a singleton bean is managed by the container, and all requests for beans with an id matching that bean definition result in that one specific bean instance being returned by the Spring container.
  • Prototype Scope - Prototype scope for a bean results in the creation of a new bean instance every time a request for that specific bean is made.

Now we are confronted with a situation when we want to inject a prototype scoped bean into a singleton scoped bean. Since dependencies are resolved at instantiation time. Thus if you dependency-inject a prototype-scoped bean into a singleton-scoped bean, a new prototype bean is instantiated and then dependency-injected into the singleton bean.

The prototype instance is the sole instance that is ever supplied to the singleton scoped bean. You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that dependency injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.

But that's not what you want, you have given a bean prototype scope with an intention that new instance of it should be created every time.

So let's see the problem first with some code. Let's say you have two classes RequestManager and RequestHandler. Where RequestManager is configured as a singleton bean where as RequestHandler is defined with a prototype scope.

<bean id="requestManager" class="org.netjs.prog.RequestManager">
       <property name="requestHandler" ref="requestHandler" ></property>
</bean>
  
<bean id="requestHandler" class="org.netjs.prog.RequestHandler" scope="prototype">

</bean>

RequestManager Class

public class RequestManager {
 private RequestHandler requestHandler;
 
 public void handleRequest(){
  requestHandler.handleRequest();
 }

 public RequestHandler getRequestHandler() {
  return requestHandler;
 }

 public void setRequestHandler(RequestHandler requestHandler) {
  this.requestHandler = requestHandler;
 }

}

RequestHandler Class

public class RequestHandler {
 RequestHandler(){
  System.out.println("In Request Handler Constructor");
 }
 public void handleRequest(){
  System.out.println("Handling request");
 }
}

Now if you run this code, using this class -

public class App {
    public static void main( String[] args ){  
     //AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
     ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
        RequestManager bean = (RequestManager) context.getBean("requestManager");
        // calling method three times
        bean.handleRequest();
        bean.handleRequest();
        bean.handleRequest();
        context.close();
    }
}

Output

In Request Handler Constructor
Handling request
Handling request
Handling request

Here, though method is called thrice, constructor is called only once which means RequestHandler instance is created only once.

Solutions

There are 3 solutions to ensure that the new instance are created every time for prototype scoped beans.

  1. Implementing the ApplicationContextAware interface.
  2. Lookup method injection
  3. aop:scoped-proxy

Implementing the ApplicationContextAware interface

One solution is to implement the ApplicationContextAware interface in that case RequestManager class will look like this. Note that according to the Spring docs this is not a good solution because the business code is aware of and coupled to the Spring Framework (look at the imports in the code). So if you want you can safely skip to the "Lookup method injection" solution.

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class RequestManager implements ApplicationContextAware{
 private RequestHandler requestHandler;
 private ApplicationContext applicationContext;
 public void handleRequest(){
  requestHandler = getRequestHandler();
  requestHandler.handleRequest();
 }
      // method to return new instance
 public RequestHandler getRequestHandler() {
  return applicationContext.getBean("requestHandler", RequestHandler.class);
  //return requestHandler;
 }

 /*public void setRequestHandler(RequestHandler requestHandler) {
  this.requestHandler = requestHandler;
 }*/

 @Override
 public void setApplicationContext(ApplicationContext applicationContext)
   throws BeansException {
  this.applicationContext = applicationContext; 
 }
}

And in XML configuration reference for RequestHandler will be removed from the RequestManager configuration.

<bean id="requestManager" class="org.netjs.prog.RequestManager">
       
</bean>
  
<bean id="requestHandler" class="org.netjs.prog.RequestHandler" scope="prototype">

Lookup method injection

Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to generate dynamically a subclass that overrides the method.

In this case the XML Configuration will look like this

<bean id="requestManager" class="org.netjs.prog.RequestManager">
       <lookup-method name="getRequestHandler" bean="requestHandler"/>
</bean>
  
<bean id="requestHandler" class="org.netjs.prog.RequestHandler" scope="prototype">

Note that the bean which is defined with the look up method will be dynamically subclassed by the Spring framework (using CGLIB library) and this subclass will override and provide implementation for the methods which are configured as look-up method.

The dynamically generated proxy will delegate all the non-lookup methods to the original class. For the lookup methods it will use the implementation it has provided.

Since look-up method has to be implemented so it has to be either defined as abstract method or you can provide some dummy implementation.

If the method is abstract, the dynamically-generated subclass implements the method. Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class.

If you are providing a dummy implementation then your RequestManager class will look like this -

public class RequestManager{
 private RequestHandler requestHandler;
 public void handleRequest(){
  requestHandler = getRequestHandler();
  requestHandler.handleRequest();
 }
 
 // dummy implmentation, configured as look-up method
 public RequestHandler getRequestHandler() {
  return null;
 }
}

In case you are defining the method as abstract then you will have to mark the class also as abstract class. It may create problem with in your whole implementation and also make the unit-testing difficult. Anyway in case you want it to be an abstract method then the RequestManager class will look like this -

public abstract class RequestManager{
 private RequestHandler requestHandler;
 public void handleRequest(){
  requestHandler = getRequestHandler();
  requestHandler.handleRequest();
 }
 
 public abstract RequestHandler getRequestHandler(); 
}

Now if you run it using this test class -

public class App {
    public static void main( String[] args ){  
       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
        RequestManager bean = (RequestManager) context.getBean("requestManager");
        bean.handleRequest();
        bean.handleRequest();
        bean.handleRequest();
        context.close();
    }
}

Output

In Request Handler Constructor
Handling request
In Request Handler Constructor
Handling request
In Request Handler Constructor
Handling request

Now you can see that three instances of RequestHandler are created for three separate calls.

Some of the points to remember when using look-up method -

  • For this dynamic subclassing to work, the class that the Spring bean container will subclass cannot be final, and the method to be overridden cannot be final either.
  • Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.
  • Concrete methods are also necessary for component scanning which requires concrete classes to pick up.

Using aop:scoped-proxy

Third way is using aop scoped proxy. Though Spring docs say "You do not need to use the <aop:scoped-proxy/> in conjunction with beans that are scoped as singletons or prototypes." As it is more suitable to be used in the scenario when you are working with request, session and application scope and want to resolve the problem of how long do you want your bean to live.

As Spring docs say "you don't" not "you shouldn't" so we can anyway use it with singleton and prototype too.

When using aop scoped proxy the XML configuration will look like this -

<bean id="requestManager" class="org.netjs.prog.RequestManager">
       <property name="requestHandler" ref="requestHandler"/>
</bean>
<bean id="requestHandler" class="org.netjs.prog.RequestHandler" scope="prototype">
    <aop:scoped-proxy/>
</bean>

Note that with look up method solution it was the singleton bean which was getting proxied but with aop scoped proxy it is the prototype bean which will be proxied.

So if we take our classes as example, the container will create a proxy object of the RequestHandler which can fetch the real RequestHandler class object from the defined scoping mechanism (prototype, request, session etc.)

The container injects this proxy object into the requestManager bean, which is unaware that this requestHandler reference is a proxy.

When a RequestManager instance invokes a method on the dependency-injected RequestHandler object, it actually is invoking a method on the proxy. The proxy then fetches the real RequestHandler object and delegates the method invocation onto the retrieved real RequestHandler object.

There are 2 ways to create proxy class using aop scoped proxy.

  1. Using CGLIB library, this is the default option.
  2. Using JDK interface-based proxies for such scoped beans, by specifying false for the value of the proxy-target-class attribute of the <aop:scoped-proxy/> <aop:scoped-proxy proxy-target-class="false" />

RequestManager Class when using aop scoped proxy

public class RequestManager{
 private RequestHandler requestHandler;
 public void handleRequest(){
  requestHandler.handleRequest();
 }
 public RequestHandler getRequestHandler() {
  return requestHandler;
 }
 public void setRequestHandler(RequestHandler requestHandler) {
  this.requestHandler = requestHandler;
 }
}

RequestHandler Class

public class RequestHandler {
 RequestHandler(){
  System.out.println("In Request Handler Constructor");
 }
 public void handleRequest(){
  System.out.println("Handling request");
 }
}

Output

In Request Handler Constructor
Handling request
In Request Handler Constructor
Handling request
In Request Handler Constructor
Handling request

That's all for this topic Injecting prototype bean in singleton. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What is Dependency Injection in Spring
  2. Spring example program using XML configuration
  3. Spring example program using automatic configuration
  4. Different bean scopes in Spring
  5. Wiring collections in Spring

You may also like -

>>>Go to Spring tutorial page

Monday, 22 February 2016

Difference between HashMap and ConcurrentHashMap in Java

ConcurrentHashMap was added in Java 5 as an alternative for HashTable to improve the performance of the (key, value) pair kind of data structure while still keeping it thread safe. On the other hand HashMap which is not synchronized provides better performance but it is not thread safe.

In this post we'll see the differences between the ConcurrentHashMap and HashMap which is also a good Java interview question.

Difference between ConcurrentHashMap and HashMap

  1. First and foremost difference is of course thread safety. ConcurrentHashMap is thread safe and fit for use in a multi-threaded environment whereas HashMap is not thread safe.
  2. Second difference is about how these data structures synchronize. HashMap can be synchronized using the Collections.synchronizedMap() method but that synchronizes all the methods of the HashMap and effectively reduces it to a data structure where one thread can enter at a time.

    In ConcurrentHashMap synchronization is done a little differently. Rather than locking every method on a common lock, ConcurrentHashMap uses separate lock for separate buckets thus locking only a portion of the Map.

    By default there are 16 buckets and also separate locks for separate buckets. So the default concurrency level is 16. That means theoretically any given time 16 threads can access ConcurrentHashMap if they all are going to separate buckets.

  3. In ConcurrentHashMap performance is further improved by providing read access concurrently without any blocking. Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove).
  4. HashMap allows one null as key but ConcurrentHashMap doesn't allow null as key.

  5. Performace wise HashMap is better as there is no synchronization.

    In case HashMap has to be used in a multi-threaded environment and there is a need to use Collections.SynchronizedMap() method then ConcurrentHashMap() is a better choice as ConcurrentHashMap still gives a chance to more than one thread to access map thus improving performance.

  6. Iterator provided by ConcurrentHashMap is fail-safe which means it will not throw ConcurrentModificationException if the underlying structure is changed during iteration.

    Iterator provided by HashMap is fail-fast as it throws a ConcurrentModificationException if the underlying collection is structurally modified at any time after the iterator is created.

That's all for this topic Difference between HashMap and ConcurrentHashMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java
  2. CopyOnWriteArrayList in Java
  3. How HashMap internally works in Java
  4. Semaphore in Java concurrency
  5. ReentrantLock in Java concurrency
  6. Java Concurrency interview questions

You may also like -

Thursday, 18 February 2016

How to add double quotes to a String in Java

You may come across a scenario when you would want to add double quotes to a String, but Java uses double quotes while initializing a String so it won't recognize that double quotes should be added with the String.

You should have guessed what needed to be done in this case. Yes you need escape character "\" to escape quotes. So let's see an example.

Example code

public class SetQuote {

 public static void main(String[] args) {
    // escaping the double quotes as quotes are
    // needed with in the String
  String value = "\"Ram\"";
  System.out.println("Value - " + value );
 }
}

Output

Value - "Ram"

Let's take another example. You have got a String and you want to enclose part of it in double quotes.

As example in XML you are reading first line has no double quotes.

You got it as

<?xml version=1.0 encoding=UTF-8?>

but it should be

<?xml version="1.0" encoding="UTF-8"?>

That can be done by using replace method of the String and escaping double quotes.

public class SetQuote {
    public static void main(String[] args) {
        SetQuote setQuote = new SetQuote();
        //String value = "\"Ram\"";
        //System.out.println("Value - " + value );
        setQuote.replaceQuote();
    }
  
    public void replaceQuote(){
        String xmlString = "<?xml version=1.0 encoding=UTF-8?>";
        xmlString = xmlString.replace("1.0", "\"1.0\"").replace("UTF-8", "\"UTF-8\"");
        System.out.println("xmlString " + xmlString);
    }
}

Output

xmlString - <?xml version="1.0" encoding="UTF-8"?>

That's all for this topic How to add double quotes to a String. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Count number of words in a String
  2. Count total number of times each character appears in a String
  3. How to sort arraylist of custom objects in Java
  4. Converting int to string - Java Program
  5. How to read file from the last line in Java

You may also like -

>>>Go to Java Programs page

Wednesday, 17 February 2016

ArrayBlockingQueue in Java Concurrency

ArrayBlockingQueue which is an implementation of the BlockingQueue interface was added in Java 5 along with other concurrent utilities like CopyOnWriteArrayList, ReentrantReadWriteLock, Exchanger, CountDownLatch etc.

ArrayBlockingQueue is a bounded blocking queue which internally uses an array to store elements. ArrayBlockingQueue orders elements in FIFO (first-in-first-out) order. When new elements are inserted, those are inserted at the tail of the queue. At the time of retrieval, elements are retrieved from the head of the queue.

Since ArrayBlockingQueue is bounded it means it has to be created with some initial capacity and that capacity cannot be changed later. Attempts to put an element into a full queue will result in the operation blocking; attempts to take an element from an empty queue will similarly block.

ArrayBlockingQueue Constructors

  1. ArrayBlockingQueue(int capacity) - Creates an ArrayBlockingQueue with the given (fixed) capacity and default access policy.
  2. ArrayBlockingQueue(int capacity, boolean fair) - Creates an ArrayBlockingQueue with the given (fixed) capacity and the specified access policy. A queue created with fairness set to true grants access to waiting producer and consumer threads in FIFO order.
  3. ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) - Creates an ArrayBlockingQueue with the given (fixed) capacity, the specified access policy and initially containing the elements of the given collection, added in traversal order of the collection's iterator.

Example code

Let's create a producer consumer using the ArrayBlockingQueue. Initial capacity of the ArrayBlockingQueue will be kept one so that producer and consumer both get a chance alternatively.

Values will be inserted in the ArrayBlockingQueue using put() method, which will block if the space is full.

Values will be retrieved from the ArrayBlockingQueue using take() method, which retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ArrayBQDemo {

    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        // Starting two threads
        ExecutorService executor = Executors.newFixedThreadPool(2);
        executor.execute(new ProdTask(buffer));
        executor.execute(new ConTask(buffer));
        executor.shutdown();
    }

}

/**
 * 
 * 
 *
 */
class ProdTask implements Runnable{
    Buffer buffer;
    ProdTask(Buffer buffer){
        this.buffer = buffer;
    }
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            buffer.put(i);
        }
    }
}

/**
 * 
 * 
 *
 */
class ConTask implements Runnable{
    Buffer buffer;
    ConTask(Buffer buffer){
        this.buffer = buffer;
    }
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            buffer.get();;
        }
    }    
}

//Shared class used by threads
class Buffer{
    int i;
    // Bouded ArrayBlockingQueue of size 1
    BlockingQueue<Integer> arrayBlockingQ = new ArrayBlockingQueue<Integer>(1);
    public void get(){
        try {
            // take method to get from blockingqueue
            System.out.println("Consumer recd - " + arrayBlockingQ.take());
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void put(int i){
        this.i = i;
        try {
            // putting in blocking queue
            arrayBlockingQ.put(i);
            System.out.println("Putting - " + i);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}

Output

Putting - 0
Consumer recd - 0
Putting - 1
Consumer recd - 1
Putting - 2
Consumer recd - 2
Putting - 3
Consumer recd - 3
Putting - 4
Consumer recd - 4

Here Buffer is the shared class used by both the producer and consumer threads. Two threads are created here one as producer thread and another as consumer thread.

Compare this producer-consumer implementation with the producer-consumer implementation using semaphore or with the producer-consumer implementation using wait-notify and you will see how much simplified it is using a BlockingQueue implementation.

That's all for this topic ArrayBlockingQueue in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. BlockingQueue in Java Concurrency
  2. PriorityBlockingQueue in Java Concurrency
  3. Difference between CountDownLatch and CyclicBarrier
  4. ReentrantReadWriteLock in Java
  5. Java Concurrency interview questions

You may also like -

Tuesday, 16 February 2016

BlockingQueue in Java Concurrency

BlockingQueue, an interface is added in Java 5 with in the java.util.concurrent package which provides many other concurrent utilities like CyclicBarrier, Phaser, ConcurrentHashMap, ReentranctLock etc.

BlockingQueue as the name suggests is a queue that can block the operations. Which means BlockingQueue supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.

For that BlockingQueue interface has two specific methods -

  1. put(E e) - Inserts the specified element into this queue, waiting if necessary for space to become available.
  2. take() - Retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

BlockingQueue Methods

BlockingQueue methods come in four forms -

Throws exception Special value Blocks Times out
Insert add(e) offer(e) put(e) offer(e, time, unit)
Remove remove() poll() take() poll(time, unit)
Examine element() peek() not applicable not applicable
  1. Methods in first column throw exception if the operation cannot be executed immediately i.e. these methods won't block.
  2. Methods in second column return a special value (either null or false, depending on the operation) if operation cannot be performed immediately.
  3. Methods in third column will block the current thread indefinitely until the operation can succeed.
  4. Methods in fourth column block for only a given maximum time limit before giving up.

No nulls

A BlockingQueue does not accept null elements. Implementations (like LinkedBlockingQueue or ArrayBlockingQueue) throw NullPointerException on attempts to add, put or offer a null.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BQDemo {
    public static void main(String[] args) {
        BlockingQueue<String> arrayBlockingQ = new ArrayBlockingQueue<String>(2);
        try {
            arrayBlockingQ.put(null);
        } catch (InterruptedException e) {
            System.out.println("Exception occurred" + e);
        }
    }
}

Output

Exception in thread "main" java.lang.NullPointerException
 at java.util.concurrent.ArrayBlockingQueue.checkNotNull(Unknown Source)
 at java.util.concurrent.ArrayBlockingQueue.put(Unknown Source)
 at org.netjs.prgrm.BQDemo.main(BQDemo.java:10)

BlockingQueue Superinterfaces

BlockingQueue extends Collection, Queue and Iterable interfaces so it inherits all Collection and Queue methods.

As exp. add(E e), remove(Object o) from the Collection interface which are different from the other two methods put() and take() in the way that add() and remove() don't block, they throw exception if the operation cannot be executed immediately.

poll() and peek() operations from Queue interface where

  • poll() - Retrieves and removes the head of this queue, or returns null if this queue is empty.
  • peek() - Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.

BlockingQueue implementations are thread-safe

BlockingQueue implementations like ArrayBlockingQueue, LinkedBlockingQueue are thread-safe. All queuing methods use internal locks or other forms of concurrency control to achieve their effects atomically.

Since BlockingQueue interface also extends Collection interface so it inherits operations from Collection interface also. However, the bulk Collection operations addAll, containsAll, retainAll and removeAll are not necessarily performed atomically unless specified otherwise in an implementation. So it is possible, for example, for addAll(c) to fail (throwing an exception) after adding only some of the elements in c.

BlockingQueue capacity

A BlockingQueue may be capacity bounded or unbounded. At any given time it may have a remainingCapacity beyond which no additional elements can be put without blocking.

For a bounded BlockingQueue implementation we have to create the BlockingQueue with the given (fixed) capacity.

As exp. ArrayBlockingQueue for which capacity has to be specified.

BlockingQueue<String> arrayBlockingQ = new ArrayBlockingQueue<String>(2);

In case of LinkedBlockingQueue or PriorityBlockingQueue both can be bounded or unbounded.

BlockingQueue<String> linkedBlockingQ = new LinkedBlockingQueue<String>(2);
        
Queue<String> linkedBlockingQ = new LinkedBlockingQueue<String>();
So both are ok.

Note that a BlockingQueue without any intrinsic capacity constraints always reports a remaining capacity of Integer.MAX_VALUE.

BlockingQueue Usage

BlockingQueue implementations are designed to be used primarily for producer-consumer queues because of the blocking methods put() and take() which facilitates inter-thread communication.

It can also be used as a bounded buffer. Let's say you have a ArrayBlockingQueue of capacity 10. So one thread can keep putting values in it and another thread can read from it once the buffer is full thus creating a bounded buffer.

At any time if all 10 slots are filled put() will block and same way for take() if there are no elements to read it will block.

Example Code

public static void main(String[] args) {
    BlockingQueue<String> arrayBlockingQ = new ArrayBlockingQueue<String>(2);
    try {
              arrayBlockingQ.put("A");
              arrayBlockingQ.put("B");
              System.out.println("------ 1 -------");
              arrayBlockingQ.forEach(a->System.out.println(a));
              arrayBlockingQ.take();
              arrayBlockingQ.put("C");
              System.out.println("------ 2 -------");
              
              arrayBlockingQ.forEach(a->System.out.println(a));
          } catch (InterruptedException e) {
              System.out.println("Exception occurred" + e);
          }
}

Output

------ 1 -------
A
B
------ 2 -------
B
C

Here it can be seen how elements are added at the end, while taking it is retrieved from the head of the queue.

Implementing classes of the BlockingQueue

Source : https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

That's all for this topic BlockingQueue in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentHashMap in Java
  2. CopyOnWriteArrayList in Java
  3. Difference between CountDownLatch and CyclicBarrier
  4. Phaser in Java concurrency
  5. Synchronization in Java multithreading
  6. Java Concurrency interview questions

You may also like -

Monday, 15 February 2016

Semaphore in Java Concurrency

Semaphore is one of the synchronization aid provided by java concurrency util in Java 5 along with other synchronization aids like CountDownLatch, CyclicBarrier, Phaser and Exchanger.

The Semaphore class present in java.util.concurrent package is a counting semaphore in which a semaphore, conceptually, maintains a set of permits. Semaphore class has two methods that make use of permits -

  • acquire() - Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted. It has another overloaded version acquire(int permits).
  • release() - Releases a permit, returning it to the semaphore. It has another overloaded method release(int permits).

Here be informed that no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly thus the name Counting Semaphore.

How Semaphore works

Thread that wants to access the shared resource tries to acquire a permit using acquire() method. At that time if the Semaphore's count is greater than zero thread will acquire a permit and Semaphore's count will be decremented by one.

If Semaphore's count is zero, when thread calls acquire() method, then the thread will be blocked until a permit is available.

When thread is done with the shared resource access, it can call the release() method to release the permit. That results in the Semaphore's count incremented by one.

Semaphore class constructors

  1. Semaphore(int permits) - Creates a Semaphore with the given number of permits and nonfair fairness setting.

    If a Semaphore is initialized with 5 permits that means atmost 5 threads can call the acquire method without Calling release method.

  2. Semaphore(int permits, boolean fair) - Creates a Semaphore with the given number of permits and the given fairness setting.

    When fairness is set true, the semaphore guarantees that threads invoking any of the acquire methods are selected to obtain permits in the order in which their invocation of those methods was processed (first-in-first-out; FIFO).

Binary Semaphore

A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations), that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.

Semaphore Usage

  • Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.
  • Semaphore can also be used to facilitate inter-thread communication like in producer-consumer kind of scenario.

Let's see one example where Semaphore is used to control shared access. Here we have a shared counter and three threads using the same shared counter and trying to increment and then again decrement the count. So every thread should first increment the count to 1 and then again decrement it to 0.

Code without Semaphore

public class SemaphoreDemo {
 public static void main(String[] args) {
  SharedCounter counter = new SharedCounter();
  // Creating three threads
  Thread t1 = new Thread(counter, "Thread-A");
  Thread t2 = new Thread(counter, "Thread-B");
  Thread t3 = new Thread(counter, "Thread-C");
  t1.start();
  t2.start();
  t3.start();
 }
}

class SharedCounter  implements Runnable{
    private int c = 0;

    // incrementing the value
    public void increment() {
        try {
         // used sleep for context switching
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        c++;
    }
    // decrementing the value
    public void decrement() {    
        c--;
    }

    public int getValue() {
        return c;
    }
    
    @Override
    public void run() {
        this.increment();
        System.out.println("Value for Thread After increment - " + Thread.currentThread().getName() + " " + this.getValue());
        this.decrement();
        System.out.println("Value for Thread at last " + Thread.currentThread().getName() + " " + this.getValue());
        
    }
}

Output

Value for Thread After increment Thread-A 1
Value for Thread at last Thread-A 1
Value for Thread After increment Thread-B 2
Value for Thread at last Thread-B 0
Value for Thread After increment Thread-C 1
Value for Thread at last Thread-C 0

Here it can be seen that output has not come right. Thread-B while incrementing is still using the value which was incremented by Thread-A.

Code with Semaphore

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
 public static void main(String[] args) {
  
  Semaphore s = new Semaphore(1);
  SharedCounter counter = new SharedCounter(s);
  // Creating three threads
  Thread t1 = new Thread(counter, "Thread-A");
  Thread t2 = new Thread(counter, "Thread-B");
  Thread t3 = new Thread(counter, "Thread-C");
  t1.start();
  t2.start();
  t3.start();
 }
}

class SharedCounter implements Runnable{
 
    private int c = 0;
    private Semaphore s;
    SharedCounter(Semaphore s){
     this.s = s;
    }
    // incrementing the value
    public void increment() {
        try {
         // used sleep for context switching
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        c++;
    }
    // decrementing the value
    public void decrement() {    
        c--;
    }

    public int getValue() {
        return c;
    }
    
    @Override
    public void run() {
     try {
         // acquire method to get one permit
         s.acquire();
         this.increment();
         System.out.println("Value for Thread After increment - " + Thread.currentThread().getName() + " " + this.getValue());
         this.decrement();
         System.out.println("Value for Thread at last " + Thread.currentThread().getName() + " " + this.getValue());
         // releasing permit
         s.release();
     }
        catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }
}

Output

Value for Thread After increment - Thread-A 1
Value for Thread at last Thread-A 0
Value for Thread After increment - Thread-B 1
Value for Thread at last Thread-B 0
Value for Thread After increment - Thread-C 1
Value for Thread at last Thread-C 0

Now it can be seen that access is controlled using Semaphore. Semaphore acquires and releases a permit after it is done manipulating the shared resource.

Semaphore inter-thread communication example

Let's see another example where producer-consumer is implemented using semaphores. Idea is to have 2 semaphores when first is acquired release second, when second is acquired release first. That way shared resource has controlled access and there is inter-thread communication between the threads.

Remember unlike RentrantLock, Semaphore can be released by a thread other than the owner (as semaphores have no notion of ownership).

public class SemConProdDemo {

    public static void main(String[] args) {
        
        Shared s = new Shared();
        // Producer and Consumer threads
        Thread t1 = new Thread(new SemProducer(s), "Producer");
        Thread t2 = new Thread(new SemConsumer(s), "Consumer");
        t1.start();
        t2.start();    

    }
}

// Shared class used by threads
class Shared{
    int i;
    // 2 semaphores 
    Semaphore sc = new Semaphore(0);
    Semaphore sp = new Semaphore(1);
    
    public void get(){
        try {
            // acquiring consumer semaphore
            sc.acquire();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Got - " + i);
        // releasing producer semaphore
        sp.release();
    }
    
    public void put(int i){
        try {
            // acquiring producer semaphore
            sp.acquire();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.i = i;
        System.out.println("Putting - " + i);
        // releasing consumer semaphore
        sc.release();
    }
}

// Producer thread
class SemProducer implements Runnable{

    Shared s;
    SemProducer(Shared s){
        this.s = s;
    }
    @Override
    public void run() {
        for(int i = 0; i < 5; i++){
            s.put(i);
        }
    }            
}

// Consumer thread
class SemConsumer implements Runnable{
    Shared s;
    SemConsumer(Shared s){
         this.s = s;
    }
    
    @Override
    public void run() {    
        for(int i = 0; i < 5; i++){
           s.get();                
        }
    }
}

output

Putting - 0
Got - 0
Putting - 1
Got - 1
Putting - 2
Got - 2
Putting - 3
Got - 3
Putting - 4
Got - 4

Source : https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Semaphore.html

That's all for this topic Semaphore in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. CountDownLatch in Java concurrency
  2. CyclicBarrier in Java concurrency
  3. Exchanger in Java concurrency
  4. Phaser in Java concurrency
  5. ReentrantReadWriteLock in Java
  6. Java Concurrency interview questions

You may also like -

Thursday, 11 February 2016

How to read file from the last line in Java

There are applications where you have to read huge files line by line may be using some tool like Pentaho, Camel. Let's say these files are in the format header, records and footer and you need to check something in the footer (last line of the file) and if that condition is not met you need to reject the file. Now, reading line by line in such scenario, will be wasteful as you'll anyway reject the file in the end.

So for such scenarios it is better to read the last line (or may be last N lines) to have better throughput. In this post you will see how to read a file from the last line in Java.

In Java it can be done using RandomAccessFile which has a seek method to set the file-pointer offset, measured from the beginning of the file.

Apache Commons IO also has a ReversedLinesFileReader class which reads lines in a file reversely.

Example code using RandomAccessFile

Let's say you have a file aa.txt which has the following content -

This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
And you want to read last line of this file.
public class ReadFileLast {

 public static void main(String[] args) {
  ReadFileLast rf = new ReadFileLast();
  File file = new File("F:\\NetJS\\test\\aa.txt");
  // calling method
  rf.readFromLast(file);
  //rf.reverseLines(file);

 }
 
 // Read last line of the file
 public void readFromLast(File file){
  
        int lines = 0;
        StringBuilder builder = new StringBuilder();
        RandomAccessFile randomAccessFile = null;
        try {
         randomAccessFile = new RandomAccessFile(file, "r");
         long fileLength = file.length() - 1;
         // Set the pointer at the last of the file
         randomAccessFile.seek(fileLength);
         for(long pointer = fileLength; pointer >= 0; pointer--){
           randomAccessFile.seek(pointer);
           char c;
           // read from the last one char at the time
           c = (char)randomAccessFile.read(); 
           // break when end of the line
           if(c == '\n'){
              break;
           }
           builder.append(c);
         }
         // Since line is read from the last so it 
         // is in reverse so use reverse method to make it right
         builder.reverse();
         System.out.println("Line - " + builder.toString());
        } catch (FileNotFoundException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
        catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }finally{
           if(randomAccessFile != null){
              try {
                 randomAccessFile.close();
              } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
              }
           }
       }
  }
}

Output

Line - This is the fourth line.

Here you get the file length and then using the seek method move the pointer to that point (end of the file). From there you start reading backward char by char. Since you are reading in reverse so you need to use reverse method of the StringBuilder to make the String straight.

If you want to read n last lines of the file you can use the following method.

       // Read n lines from the end of the file
 public void readFromLast(File file, int lines){
  int readLines = 0;
        StringBuilder builder = new StringBuilder();
        RandomAccessFile randomAccessFile = null;
        try {
          randomAccessFile = new RandomAccessFile(file, "r");
          long fileLength = file.length() - 1;
          // Set the pointer at the last of the file
          randomAccessFile.seek(fileLength);
          for(long pointer = fileLength; pointer >= 0; pointer--){
            randomAccessFile.seek(pointer);
            char c;
            // read from the last one char at the time
            c = (char)randomAccessFile.read(); 
            // break when end of the line
            if(c == '\n'){
              readLines++;
              if(readLines == lines)
               break;
            }
            builder.append(c);
          }
          // Since line is read from the last so it 
          // is in reverse so use reverse method to make it right
          builder.reverse();
          System.out.println("Line - " + builder.toString());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }finally{
          if(randomAccessFile != null){
             try {
                randomAccessFile.close();
             } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
             }
        }
   }
}

Using Apache Commons IO

public class ReadFileLast {

 public static void main(String[] args) {
  ReadFileLast rf = new ReadFileLast();
  File file = new File("F:\\NetJS\\test\\aa.txt");
  // calling method
  rf.reverseLines(file);

 }
 
// Reading file from the last using
// using ReversedLinesFileReader
public void reverseLines(File file){
 ReversedLinesFileReader object = null;
 try {
  object = new ReversedLinesFileReader(file);
  System.out.println("Line - " + object.readLine());
 } catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }finally{
  try {
   object.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}
}

That's all for this topic How to read file from the last line. If you have any doubt or any suggestions to make please drop a comment. Thanks!


You may also like -

>>>Go to Java Programs page

Wednesday, 10 February 2016

ReentrantReadWriteLock in Java

Even in a multi-threading application multiple reads can occur simultaneously for a shared resource. It is only when multiple writes happen simultaneously or intermix of read and write that there is a chance of writing the wrong value or reading the wrong value.

ReadWriteLock uses the same idea in order to boost the performance by having separate pair of locks.

A ReadWriteLock maintains a pair of associated locks -

  • One for read-only operations; and
  • one for writing.

The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

Note that ReadWriteLock is an interface and RentrantReadWriteLock is a concrete implementation of the interface. This post is about ReentrantReadWriteLock which has similar semantics to ReentrantLock.

Having a pair of read-write lock allows for a greater level of concurrency in accessing shared data than that permitted by a mutual exclusion lock. It exploits the fact that while only a single thread at a time (a writer thread) can modify the shared data, in many cases any number of threads can concurrently read the data (hence reader threads).

A read-write lock will improve performance over the use of a mutual exclusion lock if the frequency of reads is more than writes, duration of the read operations is more than the duration of the writes. It also depends on the contention for the data - that is, the number of threads that will try to read or write the data at the same time.

For example, a collection that is initially populated with data and thereafter infrequently modified, while being frequently searched (such as a directory of some kind) is an ideal candidate for the use of a read-write lock. However, if updates become frequent then the data spends most of its time being exclusively locked and there is little, if any increase in concurrency.

ReentrantReadWriteLock class

As already mentioned ReentrantReadWriteLock is an implementation of the ReadWriteLock interface which provides a pair of read-write lock.

Is there any acquisition preference

ReentrantReadWriteLock class does not impose a reader or writer preference ordering for lock access. Though there is an optional fairness policy. A ReentrantReadWriteLock is fair or not is specified in its constructor.

ReentrantReadWriteLock's constructor

  • ReentrantReadWriteLock() - Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
  • ReentrantReadWriteLock(boolean fair) - Creates a new ReentrantReadWriteLock with the given fairness policy.

Fair mode

When constructed as fair, threads contend for entry using an approximately arrival-order policy. When the currently held lock is released, either the longest-waiting single writer thread will be assigned the write lock, or if there is a group of reader threads waiting longer than all waiting writer threads, that group will be assigned the read lock.

Reentrancy

ReentrantReadWriteLock allows both read and write locks to reacquire read and write locks in the same fashion as done in Reentrant lock. See an example here.

Lock downgrading

ReentrantReadWriteLock also allows downgrading from the write lock to a read lock. You can first acquire a write lock, then the read lock and then release the write lock. So you are effectively left with a read lock. However, upgrading from a read lock to the write lock is not possible.

Example of downgrading

If you have a scenario where you want to read from a cache only if it is still valid, using a read lock. If cache is dirty then you need to acquire a write lock and put data in the cache again.

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReentrantDowngrade {
 Object data;
 volatile boolean cacheValid;
 ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
 
 void processCacheData(){
  // first acquire a read lock
  rwl.readLock().lock();
  // check if cache is still valid
     if (!cacheValid) {
        // Must release read lock before acquiring 
        // write lock, as upgrading not possible
        rwl.readLock().unlock();
        rwl.writeLock().lock();
        try {
          // Recheck state because another thread might have
          // acquired write lock and changed state before we did.
          if (!cacheValid) {
           // get fresh data for the cache
            data = ...
            cacheValid = true;
          }
          // Downgrade by acquiring read lock before 
          // releasing write lock
          rwl.readLock().lock();
        } finally {
      // Unlock write, still hold read
          rwl.writeLock().unlock(); 
        }
      }
     try {
      // use cache data
         use(data);
     } finally {
      // Finally release the read lock
         rwl.readLock().unlock();
     }
 }
}

Let us see another example where two threads are using the read lock and one write lock. In class ReentrantRWDemo there are two methods, get() is used to get data from the TreeMap, so read lock is used. Another method put() is used to add value to a map and uses the write lock.

There are 2 classes ReadThread which is used for reader threads and another class WriterThread is used for write threads. In the program two reader thread and one writer thread are spawned.

public class ReentrantRWDemo {
    private final Map<String, String> m = new TreeMap<String, String>();
    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    
     // get method for getting values from map
     // it can be used by many read threads simultaneously
    public String get(String key) {
        System.out.println("In get method waiting to acquire lock");
        rwl.readLock().lock();
        System.out.println("In get method acquired read lock");
        try { 
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return m.get(key); 
        }
        finally { 
            rwl.readLock().unlock(); 
            System.out.println("In get method released read lock");
        }
    }
    
    // Put method to store  key, value in a map
    // it acquires a write lock so only one thread at a time
    public String put(String key, String value) {
        System.out.println("In put method waiting to acquire lock");
        rwl.writeLock().lock();
        System.out.println("In put method acquired write lock");
        try { 
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return m.put(key, value); 
        }
        finally { 
            rwl.writeLock().unlock(); 
            System.out.println("In put method released write lock");
        }
    }
    
    public void display(){
            m.entrySet().forEach(System.out::println);
        
    }
    
    public static void main(String... args) {
        ReentrantRWDemo rwDemo = new ReentrantRWDemo();
        // Putting some values in the map
        rwDemo.put("1", "One");
        rwDemo.put("2", "Two");
        rwDemo.put("3", "Three");
        
        // Starting two read threads and one write thread
        Thread rThread1 = new Thread(new ReadThread(rwDemo));
        Thread wThread = new Thread(new WriterThread(rwDemo));
        Thread rThread2 = new Thread(new ReadThread(rwDemo));
        rThread1.start();
        wThread.start();
        rThread2.start();
        // Wait for the threads to finish, then only go for display method
        try {
            rThread1.join();
            wThread.join();
            rThread2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        rwDemo.display();
        
  }
}

class ReadThread implements Runnable {
    ReentrantRWDemo rwDemo;
    ReadThread(ReentrantRWDemo rwDemo){
        this.rwDemo = rwDemo;
    }
    public void run() {
        System.out.println("Value - " + rwDemo.get("1"));
    }
}

class WriterThread implements Runnable {
    ReentrantRWDemo rwDemo;
    WriterThread(ReentrantRWDemo rwDemo){
        this.rwDemo = rwDemo;
    }
    public void run() {
        rwDemo.put("4", "Four");
    }
}

Output

In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In put method waiting to acquire lock
In put method acquired write lock
In put method released write lock
In get method waiting to acquire lock
In put method waiting to acquire lock
In put method acquired write lock
In get method waiting to acquire lock
In put method released write lock
In get method acquired read lock
In get method acquired read lock
In get method released read lock
Value - One
In get method released read lock
Value - One
1=One
2=Two
3=Three
4=Four

Here you can ignore the first three set of put prints as these are the messages for the first 3 puts that are used to add values to the TreeMap. As mentioned two reader threads and one writer thread are spawned. In the display I got (for you it may vary) it can be seen that write thread first locks the shared object rwDemo, though Thread.sleep is used to introduce some delay but the reader threads will wait until the write lock is released.

But both read locks can acquire lock simultaneously as confirmed by two consecutive "In get method acquired read lock" statement.

Also note that in display() method, method reference with lambda expression is used to display the map values. These features are available from Java 8.

Thread's join method is used so that values are displayed once all the threads have finished.

That's all for this topic ReentrantReadWriteLock in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ReentrantLock in Java concurrency
  2. Difference between ReentrantLock and Synchronized
  3. CountDownLatch in Java concurrency
  4. Phaser in Java concurrency
  5. ConcurrentHashMap in Java
  6. CopyOnWriteArrayList in Java
  7. Java Concurrency interview questions

You may also like -