Training Institute in Electronic City Bangalore

Training Institute in Electronic City Bangalore
Training Institute in Electronic City Bangalore

Explain Java ThreadLocal Variables?

Today, one of the most critical aspects of a concurrent application is shared data. When you create thread that implements the Runnable interface and then start various Thread objects using the same Runnable object, all the threads share the same attributes that are defined inside the runnable object.

This essentially means that if you change any attribute in a thread, all the threads will be affected by this change and will see the modified value by first thread.

Sometimes it is desired behavior e.g. multiple threads increasing / decreasing the same counter variable; but sometimes you want to ensure that every thread MUST work on its own copy of thread instance and does not affect others data.

When to use ThreadLocal?

For example, consider you are working on an eCommerce application. You have a requirement to generate a unique transaction id for each and every customer request this controller process and you need to pass this transaction id to the business methods in manager/DAO classes for logging purpose. One solution could be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.

To solve that, here you can use ThreadLocal variable. You can generate a transaction id in controller OR any pre-processor interceptor; and set this transaction id in the ThreadLocal. After this, whatever the methods, that this controller calls, they all can access this transaction id from the threadlocal. Also note that application controller will be servicing more that one request at a time and since each request is processed in separate thread at framework level, the transaction id will be unique to each thread and will be accessible from all over the thread’s execution path.

Inside ThreadLocal Class?

The Java Concurrency API provides a clean mechanism for thread-local variables using ThreadLocal class with a very good performance.

public class ThreadLocal<T> extends Object {...}

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

This class has following methods:
·   get() : Returns the value in the current thread’s copy of this thread-local variable.
·   initialValue() : Returns the current thread’s “initial value” for this thread-local variable.
·     remove() : Removes the current thread’s value for this thread-local variable.
·   set(T value) : Sets the current thread’s copy of this thread-local variable to the specified value.

How to use ThreadLocal?

Below example uses two thread local variables i.e. threadId and startDate. Both have been defined as “private static” fields as recommended. ‘threadId‘ will be used to identify the thread which is currently running and ‘startDate‘ will be used to get the time when thread started it’s execution. Above information will be printed in console to verify that each thread has maintained it’s own copy of variables.


class DemoTask implements Runnable {
       // Atomic integer containing the next thread ID to be assigned
       private static final AtomicInteger nextId = new AtomicInteger(0);

       // Thread local variable containing each thread's ID
       private static final ThreadLocal<Integer> threadId = new ThreadLocal<Integer>(){
              @Override
              protected Integer initialValue() {
                     return nextId.getAndIncrement();
              }
       };

       // Returns the current thread's unique ID, assigning it if necessary
       public int getThreadId() {
              return threadId.get();
       }

       // Returns the current thread's starting timestamp
       private static final ThreadLocal<Date> startDate = new ThreadLocal<Date>() {
              protected Date initialValue() {
                     return new Date();
              }
       };

       @Override
       public void run() {
              System.out.printf("Starting Thread: %s : %s\n", getThreadId(),                                                                             startDate.get());
              try {
                     TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
              } catch (InterruptedException e) {
                     e.printStackTrace();
              }
              System.out.printf("Thread Finished: %s : %s\n", getThreadId(),                                                                               startDate.get());
       }
}


Now to verify that variables essentially are able to maintain their state irrespective of multiple initializations for multiple threads, let’s create three instances of this task; start the threads; and then verify the information they print in console. 


Starting Thread: 0 : Wed Dec 24 15:04:40 IST 2014
Thread Finished: 0 : Wed Dec 24 15:04:40 IST 2014

Starting Thread: 1 : Wed Dec 24 15:04:42 IST 2014
Thread Finished: 1 : Wed Dec 24 15:04:42 IST 2014

Starting Thread: 2 : Wed Dec 24 15:04:44 IST 2014
Thread Finished: 2 : Wed Dec 24 15:04:44 IST 2014

In above output, sequence of printed statement will vary every time. I have put them in sequence so that we can clearly identify that thread local values are kept safe for each thread instance; and never intermixed.

Most common use of thread local is when you have some object that is not thread-safe, but you want to avoid synchronizing access to that object using synchronized keyword/block. Instead, give each thread its own instance of the object to work with.


A good alternative to synchronization or threadlocal is to make the variable a local variable. Local variables are always thread safe. The only thing which may prevent you to do this is your application design constraints.




[Multithreading Interview Questions]


We recommend you take Big Data Hadoop class room training at eMexo Technologies in electronic city, Bangalore to learn more about Big Data Hadoop.

Explain Java Inter-thread Communication using Piped Streams?

What are piped streams

Pipe streams are just like real plumbing pipes.  You put things into to a pipe at one end using some methods.  Then you receive the same things back from the pipe stream at the other end   using some other methods. They come out in FIFO order, first-in first-out, just like from real plumbing pipes.

PipedReader and PipedWriter

PipedReader is an extension of Reader class which is used for reading character streams. Its read() method reads the connected PipedWriter’s stream. Similarly, PipedWriter is an extension of Writer class and does all the things which Reader class contracts.

A writer can be connected to a reader by following two methods:
·         Using constructor PipedWriter(PipedReader pr)
·         Using connect(PipedReader pr) method

Once connected through any of above ways, any thread can write data in stream using write(….) methods, and data will be available to reader and can be read using read() method.

Example

Below given sample program creates two threads. One thread is responsible for writing into stream and second one is only reading the data to print them in console. 

   import java.io.*;

   public class PipedCommunicationTest {
       public static void main(String[] args) {
              new PipedCommunicationTest();
       }

       public PipedCommunicationTest() {
              try {
                     // Create writer and reader instances
                     PipedReader pr = new PipedReader();
                     PipedWriter pw = new PipedWriter();
                     // Connect the writer with reader
                     pw.connect(pr);

                     // Create one writer thread and one reader thread
                     Thread thread1 = new Thread(new PipeReaderThread("ReaderThread", pr));
                     Thread thread2 = new Thread(new PipeWriterThread("WriterThread", pw));

                     // start both threads
                     thread1.start();
                     thread2.start();
              } catch (Exception e) {
                     System.out.println("PipeThread Exception: " + e);
              }
       }
   }

   class PipeReaderThread implements Runnable {
       PipedReader pr;
       String name = null;

       public PipeReaderThread(String name, PipedReader pr) {
              this.name = name;
              this.pr = pr;
       }

       public void run() {
        try {
           // continuously read data from stream and print it in console
           while (true) {
             char c = (char) pr.read(); // read a char
             if (c != -1) { // check for -1 indicating end of file
               System.out.print(c);
             }
           }
        } catch (Exception e) {
         System.out.println(" PipeThread Exception: " + e);
       }
     }
   }

   class PipeWriterThread implements Runnable {
       PipedWriter pw;
       String name = null;

       public PipeWriterThread(String name, PipedWriter pw) {
              this.name = name;
              this.pw = pw;
       }

       public void run() {
              try {
                     while (true) {
                           // Write some data after every two seconds
                           pw.write("Testing data written...n");
                           pw.flush();
                           Thread.sleep(2000);
                     }
              } catch (Exception e) {
                     System.out.println(" PipeThread Exception: " + e);
              }
       }
    }

Important notes

·   You cannot write to a pipe without having some sort of reader created and connected to it.  In other words, both ends must be present and already connected for the writing end to work.
·    You cannot switch to another reader, to which the pipe was not originally connected, once you are done writing to a pipe.
·    You cannot read back from the pipe if you close the reader.  You can close the writing end successfully, however, and still read from the pipe.

You cannot read back from the pipe if the thread which wrote to it ends.





We recommend you take Big Data Hadoop class room training at eMexo Technologies in electronic city, Bangalore to learn more about Big Data Hadoop.

© Blogger Templates | Webtalks