Friday, May 31, 2024

Java Exception Handling Interview Questions And Answers

In this post interview questions and answers for exception handling in Java are listed. This compilation will help the Java developers in preparing for their interviews.

  1. What is Exception Handling?

    Exception Handling in Java provides a way to handle a situation when an exception is thrown and shows a meaningful message to the user and continue with the flow of the program.

    When an exceptional condition occurs with in a method, the method (where the exception occurred) creates an Exception Object and throws it. The created exception object contains information about the error, its type and the state of the program when the error occurred.

    The method where the exception is thrown may handle that exception itself or pass it on. In case it passes it on, run time system goes through the method hierarchy that had been called to get to the current method to search for a method that can handle the exception.

    Five keywords used to manage Java exception handling

    • try- Any code that might throw an exception is enclosed within a try block.
    • catch- If an exception occurs in try block, catch block can provide exception handlers to handle it in a rational manner.
    • finally- The finally block always executes when the try block exits. So, any code that must execute after a try block is completed should be put in finally block.
    • throw- throw is used to manually thrown an exception.
    • throws- Any exception that is thrown in a method but not handled there must be specified in a throws clause.
    Read more about Exception handling in Java here.

  2. Explain the exception hierarchy in Java?

    Throwable class is the super class of all the exception types. Below Throwable class there are two subclasses which denotes two distinct branches of exceptions-

    • Exception- An Exception indicates that a problem has occurred, but it is not a serious system problem. The user programs you write will throw and catch Exceptions.
    • Error- It defines exceptions that are not expected to be caught by your program. Exceptions of type Error are used by the Java run-time system to indicate errors having to do with the run-time environment, itself.
      Examples of error are StackOverflowError, OutOfMemoryError etc.
    • Below Exception there is a distinct subclass RunTimeExcpetion- RunTimeExcpetion and its descendants denote the exceptional conditions that are external to the application, and the application usually cannot anticipate or recover from them.

    Read more about exception hierarchy in Java here.

  3. What is the difference between Checked Exception and Unchecked Exception?

    Checked Exception is a direct subclass of Exception where as unchecked exception is a subclass of RunTimeException.

    Checked exception should be wrapped in a try-catch block or specified as throws clause where as there is no such requirement for unchecked exception.

    Failure to provide exception handling mechanism for checked exception result in compiler error whereas no compile time error for unchecked exception.

    Checked exceptions are designed to reduce the number of exceptions which are not properly handled and where there is a reasonable chance for recovery. UnCheckedExceptions are mostly programming errors.

    Read more about difference between Checked Exception and Unchecked Exception here.

  4. What is the difference between error and exception?

    Exception- An Exception indicates that a problem has occurred, but it is not a serious system problem. The user programs you write will throw and catch Exceptions.

    Error- It defines exceptions that are not expected to be caught by your program. Exceptions of type Error are used by the Java run-time system to indicate errors having to do with the run-time environment, itself.
    Examples of error are StackOverflowError, OutOfMemoryError etc.


  5. Is it necessary that each try block must be followed by a catch block?

    No it is not mandatory that there should be a catch block after a try block. try block can have only a matching finally block. So there are these valid combinations try-catch-finally, try-catch, try-finally.

    Read more about try-catch block here.

  6. What is finally block?

    When an exception occurs in the code, the flow of the execution may change or even end abruptly. That may cause problem if some resources were opened in the method.
    For example, if a file was opened in a method and it was not closed in the end as some exception occurred then the resources may remain open consuming memory. finally provides that exception-handling mechanism to clean up.

    Code with in the finally block will be executed after a try/catch block has completed. The finally block will be executed whether or not an exception is thrown.

    Read more about finally block here.

  7. Is it possible to have a finally block without catch?

    Yes we can have a try-finally block, catch is optional. We can have these combinations try-catch-finally, try-catch, try-finally.

    Read more about finally block here.

  8. Are you aware of any scenario when finally will not be executed?

    According to Java docs. If the JVM exits (By explicitly using System.exit() or a JVM crash) while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

    Read more about finally here.

  9. What is a nested try statement?

    A try-catch-finally block can reside inside another try-catch-finally block that is known as nested try statement.

    public class NestedTryDemo {
      public static void main(String[] args) {
        try{
          System.out.println("In Outer try block");
          try{
            System.out.println("In Inner try block");
            int a = 7 / 0;
          }catch (IllegalArgumentException e) {
            System.out.println("IllegalArgumentException caught");
          }finally{
            System.out.println("In Inner finally");
          }
        }catch (ArithmeticException e) {
          System.out.println("ArithmeticException caught");
        }finally {
          System.out.println("In Outer finally");
        }
      }
    }
    
    Read more about nested try statement here.

  10. What are multiple catch blocks?

    There might be a case when a code enclosed with in a try block throws more than one exception. To handle these types of situations, two or more catch clauses can be specified where each catch clause catches a different type of exception. When an exception is thrown, each of the catch statement is inspected in order, and the first one whose type matches that of the thrown exception is executed.

    int a[] = {0};
    try{
      int b = 7/a[i];
    }catch(ArithmeticException aExp){
      aExp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException aiExp){
      aiExp.printStackTrace();
    }
    
    Read more about multiple catch blocks here.

  11. What is exception propagation?

    When an exceptional condition occurs within a method, the method (where the exception occurred) creates an Exception Object and throws it. The created exception object contains information about the error, its type and the state of the program when the error occurred.
    The method where the exception is thrown may handle that exception itself or pass it on. In case it passes it on, run time system goes through the method hierarchy that had been called to get to the current method to search for a method that can handle the exception.
    If your program is not able to catch any particular exception, that will ultimately be processed by the default handler. This process of going through the method stack is known as Exception propagation.

    Read more about exception propagation here.

  12. What is throw keyword?

    It is possible for a Java program to throw an exception explicitly that is done using the throw statement.

    The general form of throw is-
    throw throwableObject;

    We can get this throwableObject in 2 ways-
    • By using the Exception parameter of catch block.
    • Create a new one using the new operator.
    try{
       throw new NullPointerException();   
      }catch(NullPointerException nExp){
       System.out.println("Exception caught in catch block of displayValue");
       throw nExp;
      }
     }
    
    Read more about throw keyword here.

  13. What is throws clause?

    If in a method we don't want to handle any exception but want to leave it to the calling method to handle any exception that is thrown by the called method, it is done using throws keyword.

    Using throws a method can just declare the exception it may throw and callers of the method have to provide exception handling for those exceptions (or they can also declare them using throws).

    General form of a method declaration that includes a throws clause

    type method-name(parameter-list) throws exception-list
    {
    // body of method
    }
    
    Here, exception-list is a comma-separated list of the exceptions that a method can throw.
    Read more about throws clause here.

  14. Difference between throw and throws?

    • throw is used to throw an exception.
    • throws is used to declare an exception, in the method signature, that can be thrown from a method.
    Read more about difference between throw and throws here.

  15. final Vs finally Vs finalize

    • final- final keyword is used to restrict in some way. It can be used with variables, methods and classes. When a variable is declared as final, its value can not be changed once it is initialized. Except in case of blank final variable, which must be initialized in the constructor.
      If you make a method final in Java, that method can't be overridden in a sub class.
      If a class is declared as final then it can not be sub classed.
    • finally- finally is part of exception handling mechanism in Java. finally block is used with try-catch block. finally block is always executed whether any exception is thrown or not and raised exception is handled in catch block or not. Since finally block always executes thus it is primarily used to close the opened resources like database connection, file handles etc.
    • finalize()- finalize() method is a protected method of java.lang.Object class. Since it is in Object class thus it is inherited by every class. This method is called by garbage collector thread before removing an object from the memory. This method can be overridden by a class to provide any cleanup operation and gives object final chance to cleanup before getting garbage collected.
      protected void finalize() throws Throwable
      {
        //resource clean up operations
      }
      
    Read more about final Vs finally Vs finalize here.

  16. What are the rules of exception handling with respect to method overriding?

    There are certain restrictions while overriding a method in case of exception handling in Java. Broadly there are two rules-

    • If superclass method has not declared any exception using throws clause then subclass overridden method can't declare any checked exception though it can declare unchecked exception.
    • If superclass method has declared an exception using throws clause then subclass overridden method can do one of the three things.
      • sub-class can declare the same exception as declared in the super-class method.
      • subclass can declare the subtype exception of the exception declared in the superclass method. But subclass method can not declare any exception that is up in the hierarchy than the exception declared in the super class method.
      • subclass method can choose not to declare any exception at all.
    Read more about exception handling and method overriding here.

  17. What is the error in the following code?

    class Parent{
       public void displayMsg() throws IOException{
         System.out.println("In Parent displayMsg()");
        throw new IOException("Problem in method - displayMsg - Parent");
       }
    }
    public class ExceptionOverrideDemo extends Parent{
      public void displayMsg() throws Exception{  
        System.out.println("In ExceptionOverrideDemo displayMsg()"); 
        throw new Exception("Problem in method - displayMsg - ExceptionOverrideDemo");
      }  
    }
     

    Here parent class had declared IOException where as subclass has declared Exception. Exception is the super class of IOException thus it is wrong according to the rules of method overriding and exception handling. Thus the code will give compiler error.

    Read more about exception handling and method overriding here.

  18. What is multi-catch statement in Java 7?

    Before Java 7 multi-catch statement, if two or more exceptions were handled in the same way, we still had to write separate catch blocks for handling them.

    catch(IOException exp){
      logger.error(exp);
      throw exp;
    }catch(SQLException exp){
      logger.error(exp);
      throw exp;
    }
    

    With Java 7 and later it is possible to catch multiple exceptions in one catch block, which eliminates the duplicated code. Each exception type within the multi-catch statement is separated by Pipe symbol (|).

    catch(IOException | SQLException exp){
      logger.error(exp);
      throw exp;
    }
    
    Read more about multi-catch statement in Java 7 here.

  19. What is try-with-resources or ARM in Java 7?

    Java 7 introduced a new form of try known as try-with-resources for Automatic Resource Management (ARM). Here resource is an object that must be closed after the program is finished with it. Example of resources would be an opened file handle or database connection etc.

    Before the introduction of try-with-resources we had to explicitly close the resources once the try block completes normally or abruptly.

    try {
        br = new BufferedReader(new FileReader("C:\\test.txt"));
        System.out.println(br.readLine());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
      try {
        if (br != null){
          System.out.println("Closing the file");
          br.close();
        }                
      } catch (IOException ex) {
        ex.printStackTrace();
      }
    }
    

    try-with-resources helps in reducing such boiler plate code. Let's see the same example using try-with-resources.

    try(BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"))) {            
      System.out.println(br.readLine());
    } catch (IOException e) {
      e.printStackTrace();
    } 
    
    Read more about try-with-resources in Java 7 here.

  20. When is custom exception class needed? How to create a custom exception class?

    According to Java Docs, you should write your own exception classes if you answer yes to any of the following questions; otherwise, you can probably use someone else's.

    • Do you need an exception type that isn't represented by those in the Java platform?
    • Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors?
    • Does your code throw more than one related exception?
    • If you use someone else's exceptions, will users have access to those exceptions? A similar question is, should your package be independent and self-contained?
    Read more about creating custom exception class here.

  21. What is the difference Between StackOverflowError and OutOfMemoryError in Java?

    StackOverflowError- Whenever you run any Java program even if you don’t explicitly create any thread a main thread is started and that thread runs the program. For each thread JVM creates a stack, whenever any method is invoked a new frame is created and pushed into the JVM stack for the thread. Each frame stores data corresponding to the invoked method including local variables, operand stack and a reference to the run-time constant pool and reference to exception table. Once the method execution is completed corresponding stack frame is popped out of the stack.
    JVM throws StackOverflowError if the stack memory requirement of any method exceeds the permitted stack memory size.

    OutOfMemoryError- In Java, memory for each object, for arrays and for instance variables (variables at class level not method level) is created on the heap. When there are no references to an object that object is garbage collected thus clearing the heap memory. If you try to create an object or array that tries to take more memory than the allocated heap memory or there are a lot of objects in heap that are still referenced so can’t be garbage collected and JVM tries to allocate heap memory for a new object JVM throws java.lang.OutOfMemoryError because there is no sufficient heap memory.

    Read more about difference Between StackOverflowError and OutOfMemoryError here.

Related Topics

  1. Java Multithreading Interview Questions And Answers
  2. Java Collections Interview Questions And Answers
  3. Java String Interview Questions And Answers
  4. Core Java Basics Interview Questions And Answers
  5. Java OOP Interview Questions And Answers
  6. Java Concurrency Interview Questions And Answers
  7. Java Lambda Expressions Interview Questions And Answers
  8. Java Stream API Interview Questions And Answers

NodeJS Blocking Non-blocking Code

If you are doing programming from some time, you would have definitely heard the terms blocking and non-blocking or synchronous and asynchronous. NodeJS, which uses event-driven architecture, is also capable of performing non-blocking operations even though JavaScript is single-threaded thanks to the event loop in NodeJS.

What is Blocking code

If your code is executing synchronously that means it is executing line by line if there is a function call, control waits for function execution to finish. Which means execution of any further operation is blocked until the current operation completes.

In terms of Node.js, blocking code means the execution of additional JavaScript in the Node.js process is blocked until a non-JavaScript operation completes.

For example, if you are reading a file synchronously then the actual operation of reading the file content (non-JavaScript operation) blocks any other operation until reading the file completes.

Node.js blocking code example

In the 'fs' module there is a function readFileSync() that reads the file synchronously. Using that let's see how any other operation is blocked.

In the code there is a function readFileBlocking() which takes file path as parameter and then call fs.readFileSync() with that file to read the file synchronously. Content of the file is also logged to the console.

The function readFileBlocking() is called twice to read files Hello.txt and message.txt which reside in the project root directory.

const fs = require('fs');
const path = require('path');

const readFileBlocking = (filePath) => {
    console.log('Started reading ' + filePath);
    const data = fs.readFileSync(filePath, {encoding:'utf8'});
    console.log(data);
    console.log('Finished reading ' + filePath);
}

readFileBlocking(path.join(__dirname, 'Hello.txt'));
readFileBlocking(path.join(__dirname, 'message.txt'));
console.log('Waiting for file to be read....');

On running this code output is as given below for my project structure and the content I have in the two files.

Started reading D:\NETJS\NodeJS\nodews\Hello.txt
Hello from nodeJS
Finished reading D:\NETJS\NodeJS\nodews \Hello.txt
Started reading D:\NETJS\NodeJS\nodews \message.txt
This is a message from NodeJS
Finished reading D:\NETJS\NodeJS\nodews\message.txt
Waiting for file to be read....

Thing to note here is that reading of second file starts only after finishing the read operation for the first file, until then it is blocked. The message 'Waiting for file to be read....' is also displayed at the end after finishing the I/O operations. Actually this message will make more sense with the asynchronous operation here it should be changed to

console.log('File operations completed....');

What is non-blocking code

If your code is executing asynchronously that means it may not follow the convention of executing code line by line.

With non-blocking code If there is a function call, control doesn't wait for function execution to finish. It moves on to the next operation.

There must be a mechanism so that control is notified once the operation in progress finishes and control can come back to the finished operation to do any further processing like returning any data, use data in any other logic and so on.

In terms of Node.js non-blocking code means the execution of additional JavaScript in the Node.js process is not blocked until a non-JavaScript operation completes. There is a callback function which executes for any further processing once the non-JavaScript operation completes. For example, if you are reading a file asynchronously then the actual operation of reading the file content (non-JavaScript operation) doesn't block any other operation until reading the file completes.

Node.js non-blocking code example

In the 'fs' module there is a function readFile() that reads the file asynchronously.

In the code there is a function readFileNonBlocking() which takes file path as parameter and then call fs.readFile() with that file to read the file asynchronously. Content of the file is also logged to the console.

The function readFileNonBlocking() is called twice to read files Hello.txt and message.txt which reside in the project root directory.

const fs = require('fs');
const path = require('path');

const readFileNonBlocking = (filePath) => {
    console.log('Started reading ' + filePath);
    fs.readFile(filePath, 'utf8', (err, data) => {
        if(err){
            console.error('Error while reading file', err);
            return;
        }
        console.log(data); 
        console.log('Finished reading ' + filePath);       
    });
}

readFileNonBlocking(path.join(__dirname, 'Hello.txt'));
readFileNonBlocking(path.join(__dirname, 'message.txt'));
console.log('Waiting for file to be read....');

On running this code output is as given below for my project structure and the content I have in the two files.

Started reading D:\NETJS\NodeJS\nodews\Hello.txt
Started reading D:\NETJS\NodeJS\nodews\message.txt
Waiting for file to be read....
Hello from nodeJS
Finished reading D:\NETJS\NodeJS\nodews\Hello.txt
This is a message from NodeJS
Finished reading D:\NETJS\NodeJS\nodews\message.txt

From the output you can notice that operation is not getting blocked at fs.readFile() while the file is getting read control moves on to the next operation which also happens to be another file read operation so the control moves on to the next operation while the other file is getting read. That's why message 'Waiting for file to be read....' is displayed first.

Once the file read operation completes, callback function is called which display the file content.

You can compare the output of this example to the output of the blocking example to get better clarity.

That's all for this topic NodeJS Blocking Non-blocking Code. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Introduction to Node.js
  2. Node.js REPL
  3. Creating HTTP server in Node.js
  4. How to Setup a Node.js Project
  5. NodeJS NPM Package Manager

You may also like-

  1. Reading a File in Node.js
  2. JavaScript Rest Parameter
  3. Angular Event Binding With Examples
  4. NgNonBindable Directive in Angular
  5. Array in Java With Examples
  6. Fix Scanner.nextLine() Skipping Input After Another next Methods
  7. Difference Between @Controller And @RestController Annotations in Spring
  8. Python First Program - Hello World

Thursday, May 30, 2024

Node.js Event Driven Architecture

In this article we'll talk about the event-driven architecture of Node.js and how it makes Node.js more efficient, scalable and non-blocking.

What is event-driven architecture

Event-driven architecture uses events to trigger processing. You can think of it as one entity which emits an event and another entity that handles that event. An event is a change in state, with JavaScript in browser it can be a keyboard button press event, mouse click event and so on.

Event-driven architecture promotes loose coupling making the system scalable, more responsive and extensible.

Features of event-driven architecture

Some of the features of event-driven architecture are as given below-

  1. Asynchronous- In event-drive architecture events are processed asynchronously. Generally, a system that can store fired events and process them concurrently is used which means event handler is not blocked and remains responsive.
    NodeJS event-driven programming
  2. Loosely-coupled- In event-driven architecture communication between entities is handled using events. One entity emitting the event and another entity handling it keeping both of the entities independent of each other.
  3. Scalable- Because of the loosely coupled architecture event-driven systems are scalable and more efficient.

Event-driven architecture in NodeJS

NodeJS follows the event-driven architecture that is why NodeJS is asynchronous and non-blocking and event loop in NodeJS plays an important role in it.

If we take example of a non-blocking IO operation in NodeJS that's how it works-

  1. With the asynchronous, non-blocking IO operation there will be an associated callback function (event handler).
  2. While an I/O operation (like reading or writing a file) is in progress, NodeJS doesn't wait for I/O operations to complete. It can continue executing other tasks.
  3. Once the I/O operation is finished an event is emitted and the callback function associated with the I/O operation is added to the poll queue to eventually be executed. Event loop, while looping the pending events comes to the poll phase and executes the event handlers (callback functions) stored in the poll queue.

Here is an example of an I/O operation of reading a file using 'fs' module.

const fs = require('fs');
const path = require('path');

fs.readFile(path.join(__dirname, 'Hello.txt'), 'utf8', (err, data) => {
    if(err){
        console.error('Error while reading file', err);
        return;
    }
    console.log(data);
})

console.log('Waiting for file to be read....');

If you run this file the output is-

node app.js

Waiting for file to be read....
Hello from nodeJS

In the above code fs.readFile() is an asynchronous I/O operation.

The callback function is this part-

(err, data) => {
    if(err){
        console.error('Error while reading file', err);
        return;
    }
    console.log(data);
}

You can notice from the output that file read operation doesn't block the system that's why 'Waiting for file to be read....' message is displayed while file reading is still in progress.

When the I/O operation of reading a file completes that emits an event which leads to the execution of the callback function where the content of the file is displayed.

Node.js Event emitter

NodeJS provides functionality to build your own system of emitting and handling events by using the events module.

The events module has a class named EventEmitter which is used to handle our custom events.

You can initialize EventEmitter class as given below-

const EventEmitter = require('events');
const eventEmitter = new EventEmitter();

The eventEmitter object has the on and emit methods.

  • emit is used to trigger an event
  • on is used to add a callback function that's going to be executed when the event is triggered

NodeJS EventEmitter example

const EventEmitter = require('events');

//EventEmitter object
const eventEmitter = new EventEmitter();

// associate callback function with an event
eventEmitter.on('start', () => {
    console.log('Started event handling');
    // trigger another event
    eventEmitter.emit('data_process'); 
});


eventEmitter.on('data_process', () => {
    console.log('Processing started');
});

// trigger 'start' event
eventEmitter.emit('start'); 
  
console.log("Completed");

On running it output is as given below.

Started event handling
Processing started
Completed

That's all for this topic Node.js Event Driven Architecture. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Node.js REPL
  2. NodeJS NPM Package Manager
  3. Creating HTTP server in Node.js
  4. NodeJS Blocking Non-blocking Code
  5. JavaScript Array reduce() Method With Examples

You may also like-

  1. Angular Custom Two-Way Data Binding
  2. Directives in Angular
  3. JSX in React
  4. React HelloWorld App - First React App
  5. Method Overriding in Java
  6. Python continue Statement With Examples
  7. Spring Boot Observability - Distributed Tracing, Metrics
  8. Spring Boot Event Driven Microservice With Kafka

Wednesday, May 29, 2024

Forms in Angular

Using forms for user input is the mainstay of any frontend application. Angular framework provides a very robust API for handling forms. In Angular there are two different approaches to handling user input through forms-

  • Template-driven forms
  • Reactive forms

Both of these approaches for handling forms in Angular provides the functionality to-

  1. Capture user inputs from the UI (View)
  2. Validating user input
  3. Creating a form model and data model
  4. Provide a way to track changes in the form and update model accordingly.

Tuesday, May 28, 2024

Angular Cross Component Communication Using Subject Observable

In this post we’ll see how to use Subject observable for cross component communication in Angular.


Subject in RxJS Library

Subject is a type of Observable using which you can multicast values to many Observers, which makes it different from a plain Observables which are unicast (each subscribed Observer owns an independent execution of the Observable).

Friday, May 24, 2024

Node.js REPL

Node.js REPL which stands for Read, Evaluate, Print, Loop is an interactive session (a console window) where you can enter a single expression and get result back on the console. The REPL session provides a convenient way to quickly test simple JavaScript code.

The REPL shell Reads the JavaScript code entered by you, Evaluates the expression, Prints the result and Loops until the user quits by pressing ctrl-c twice to come out of the REPL session.

How to start REPL session

If you run the node command without any other argument, REPL session starts

D:\NETJS>node
Welcome to Node.js v18.17.0.
Type ".help" for more information.
>

At this point REPL is waiting for you to enter some JavaScript code.

REPL usage

You can start simple by logging a message to the console.

> console.log('Hello')
Hello
undefined
>

The first value 'Hello' is the output we told the console to print, then we get undefined which is the return value of running console.log().

For the expressions entered in REPL session Node does the following tasks-

  1. Node reads the code
  2. Evaluates it
  3. Prints the result
  4. Goes back to waiting for more lines of code

Node will loop through the first three steps for every piece of code we execute in the REPL until we exit the session.

Let's assign values to variables and then use those variables in arithmetic operations.

> const a = 4
undefined
> const b = 7
undefined
> console.log(a+b)
11
undefined
> console.log(a * b)
28
undefined
>

Comparing values

> 7 === '7'
false

Note that undefined is not printed this time because expression is returning a value which is 'false'.

Multiline code in REPL

You may want to test a code, which has multiple lines, using REPL. For example, you are writing a function that spans several lines. In that case if you press enter, Node REPL is smart enough to determine that you are not done writing your code yet, and it will go into a multi-line mode for you to type in more code.

> function displayMsg(name){
...

Once you write the whole function and press enter

> function displayMsg(name){
... return `Hello ${name}`;
... }
undefined

REPL detects the end of the function because of the closing curly braces. Then you can call the created function.

> displayMsg('NodeUser')
'Hello NodeUser'
>

Special _ (underscore) variable in REPL

_ (underscore) variable in REPL stores the result of the last operation.

> 5+6
11
> const x = _
undefined
> console.log(x)
11

This statement- const x = _; assigns 11 to x as that is the value of the last operation which is stored in _.

Using Node modules

You can use Node modules also by importing them. For example using fs module to write a file from REPL.

> const fs = require('fs')
undefined
>  fs.writeFile('abc.txt', 'Hello', (err) => {
...   if (err) {
...    return console.error("Error while writing");
...   }else{
...    console.log('File written successfully');
...   }
...  })
undefined
> File written successfully

If you go the location from where you have started REPL session you should see a file named abc.txt created.

Special Dot commands in REPL

The REPL has some special commands, all starting with a dot (.). They are as given below-

  1. .help: shows the dot commands help
  2. .editor: Enables editor mode which helps you in writing multiline JavaScript code with ease. In editor mode use ctrl-D to run the code you wrote.
  3. .break: when inputting a multi-line expression, entering the .break command will abort further input. Same as pressing ctrl-C.
  4. .clear: resets the REPL context to an empty object and clears any multi-line expression currently being input.
  5. .save: Saves whatever you have entered in the REPL session to a file. For example, .save mywork.js
  6. .load: Loads the saved REPL session file. For example, .load mywork.js
  7. .exit: Exits the repl (same as pressing ctrl-C two times)

That's all for this topic Node.js REPL. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Node.js Tutorial Page


Related Topics

  1. NodeJS NPM Package Manager
  2. NodeJS Event Loop
  3. Creating HTTP server in Node.js
  4. How to Setup a Node.js Project
  5. JavaScript Import and Export

You may also like-

  1. React Virtual DOM
  2. React HelloWorld App - First React App
  3. Angular Project Structure With File Description
  4. How to Setup Angular
  5. Encapsulation in Java
  6. Java Pass by Value or Pass by Reference
  7. Callable and Future in Java With Examples
  8. Python First Program - Hello World

Thursday, May 23, 2024

How to Install Node.js and NPM in Windows

This article shows how you can download and install Node.js so that you can build network applications. Installation of Node.js is also a prerequisite for developing Angular applications.

We’ll also build a simple Node.js hello world application to verify the Node.js installation.


Downloading Node.js

You can download latest Node.js version from this location- https://nodejs.org/en/download/

Node.js download

Installing Node.js

Double click on the downloaded Windows Installer (.msi) file to start the installation.

Nodejs installation

Double click on the downloaded Windows Installer (.msi) file to start the installation. Follow the instructions which includes-

  1. Accepting the license term
  2. Select the location where you want to install nodejs.
  3. Select the components to be installed.
  4. Check the box to automatically install tools for native modules.
  5. Click install button to start installation.

Checking for NPM

The Node Pack Manager (NPM) should also get installed as part of Node.js installation. To check if it is successfully installed, run the following command from command prompt.

npm -v

It should display version number for the NPM installation.

Checking Node.js installation

To verify Node.js installation you can run a simple Node.js HelloWorld application. Save the following code as helloworld.js.

const http = require('http');

const hostname = '127.0.0.1';
const port = 9000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Here http functionality is required so first thing is to specify it using require() function.

In the script http server is created which listens on port 9000. For any request received it sends ‘Hello World’ as response.

Navigate to the directory where helloworld.js is saved and run the following command.

F:\NETJS>Node helloworld.js

That starts the server which starts listening on port 9000. You can start a browser and type the following URL.

http://localhost:9000/

nodejs hello world

That's all for this topic How to Install Node.js and NPM in Windows. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Introduction to Node.js
  2. Node.js REPL
  3. Angular Project Structure With File Description
  4. How to Setup Angular
  5. Angular First App - Hello world Example

You may also like-

  1. Angular Example to Render Multiple Rows
  2. How to Add Bootstrap to Angular Application
  3. Creating New Component in Angular
  4. Serialization in Java
  5. Object Cloning in Java
  6. Garbage Collection in Java
  7. Spring Web MVC Example With Annotations And XML Configuration
  8. Introduction to Hadoop Framework

Tuesday, May 21, 2024

Bubble Sort Program in Java

In this post we’ll see how to write Bubble sort program in Java. Out of the three simpler sorting algorithms Bubble sort, Insertion sort and Selection sort, Bubble sort is considered the simplest sorting algorithm and the slowest too because of a proportionally large number of swaps along with the comparisons.

How Bubble sort works

In bubble sort you start by comparing the first two elements (index 0 and index 1). If element at index 0 is greater than the element at index 1 then those two elements are swapped, if it is not then you do nothing. Then the next 2 elements are compared (index 1 and index 2) and elements are swapped based on the same logic.

So the steps for bubble sort are as follows-

  1. Compare the adjacent elements.
  2. If element at the left is greater than the element at the right then swap the elements.
  3. Move one position right.

You continue doing that until you reach the last element, by then you have the greatest element at the right. Since the biggest elements bubble up to the top end thus the name “Bubble sort”.

This is the first pass, in the next iteration again you start from the two leftmost elements and compare the elements and swap if required. Since the rightmost element is already in its sorted position so this iteration runs till (N-1) elements.

For example if you have an array [5, 2, 6, 1] then in the first iteration-

  1. Initially 5 is compared with 2, since 5 (element at left) is greater than 2 (element at right), elements are swapped making the array [2, 5, 6, 1].
  2. Move over one position and compare 5 and 6, since 5 is not greater than 6 so nothing is done and array remains [2, 5, 6, 1].
  3. Again move over one position and compare 6 and 1, since 6 is greater than 1 elements are swapped giving us the array as [2, 5, 1, 6].

In the next iteration last element is not included in the comparison as it is already at its final position.

Bubble Sort Java program

public class BubbleSort {

  public static void main(String[] args) {
    int[] intArr = {47, 85, 62, 34, 7, 10, 92, 106, 2, 54};
    int[] sortedArray = bubbleSort(intArr);
    System.out.println("Sorted array is- ");
    for(int num : sortedArray){
      System.out.print(num + " ");
    }
  }
    
  private static int[] bubbleSort(int[] intArr){
    // right to left 
    for(int i = intArr.length; i > 1; i--){
      for(int j = 0; j < i - 1; j++){
        //if greater swap elements
        if(intArr[j] > intArr[j+1]){
          swapElements(j, intArr);
        }
      }            
    }
    return intArr;
  }
    
  private static void swapElements(int index, int[] intArr){
    int temp = intArr[index];
    intArr[index] = intArr[index+1];
    intArr[index+1] = temp;        
  }
}

Output

Sorted array is- 
2 7 10 34 47 54 62 85 92 106 

Time and Space complexity of Bubble sort

For bubble sort there are two loops that go through the elements that makes it a complexity of N*N i.e. O(N2). In bubble sort the number of swaps is also high which makes it slow.

Bubble sort is an in place sorting algorithm so there is no auxiliary space requirement. Thus the space complexity of Bubble sort is O(1).

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

>>>Return to Java Programs Page


Related Topics

  1. Shell Sort Program in Java
  2. Tree Sort in Java Using Binary Search Tree
  3. Reverse Each Word in a String Java Program
  4. Find Duplicate Characters in a String With Repetition Count Java Program
  5. Factorial Program in Java

You may also like-

  1. Producer-Consumer Java Program Using ArrayBlockingQueue
  2. Converting String to Enum Type in Java
  3. How to Read File From The Last Line in Java
  4. Difference Between Two Dates in Java
  5. How LinkedList Class Works Internally in Java
  6. Difference Between ArrayList And CopyOnWriteArrayList in Java
  7. strictfp in Java
  8. Transaction Management in Spring

Monday, May 20, 2024

Java ReentrantReadWriteLock With Examples

This post gives an introduction to ReadWriteLock interface and it's implementing class ReentrantReadWriteLock in Java with usage examples.


ReadWriteLock 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 in Java 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.

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 in Java

As already mentioned ReentrantReadWriteLock is an implementation of the ReadWriteLock interface which provides a pair of read-write lock. ReentrantReadWriteLock has similar semantics to ReentrantLock in Java.

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

ReentrantReadWriteLock in Java 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.

Java ReentrantReadWriteLock constructors

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

Fair mode in ReentrantReadWriteLock

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.

Lock downgrading in ReentrantReadWriteLock

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 lock 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();
    }
  }
}

ReentrantReadWriteLock Java example

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 Java ReentrantReadWriteLock With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between ReentrantLock and Synchronized in Java
  2. Java StampedLock With Examples
  3. Java CountDownLatch With Examples
  4. CopyOnWriteArrayList in Java With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Executor And ExecutorService in Java With Examples
  2. Inter-thread Communication Using wait(), notify() And notifyAll() in Java
  3. Race Condition in Java Multi-Threading
  4. How and Why to Synchronize ArrayList in Java
  5. equals() And hashCode() Methods in Java
  6. Java Program to Convert a File to Byte Array
  7. @FunctionalInterface Annotation in Java
  8. Spliterator in Java

Friday, May 17, 2024

@FunctionalInterface Annotation in Java

In the post Functional Interfaces in Java we have already seen that functional interfaces are those interfaces that have only one abstract method. Java 8 also introduced an annotation @FunctionalInterface to be used with functional interfaces. Annotating an interface with @FunctionalInterface in Java indicates that an interface type declaration is intended to be a functional interface.

It is not mandatory to mark functional interface with @FunctionalInterface annotation, it is more of a best practice to do that and also gives a surety that no other abstract method will be added accidentally to the functional interface. It will result in a compile time error if any other abstract method is added to a functional interface which is annotated with @FunctionalInterface annotation.

Let's see it with some examples what is permitted and what is not with @FunctionalInterface annotation in Java.
First there is an example of a valid functional interface that is annotated with @FunctionalInterface-

 
@FunctionalInterface
public interface IMyFuncInterface {
  public void getValue();
}

In an interface annotated with @FunctionalInterface, if more than one abstract method is defined it results in compile time error.

@FunctionalInterface
public interface IMyFuncInterface {
  public void getValue();
  // Second abstract method so compiler error
  public void setValue();
}

Note that in Java 8 default methods and static methods are also added in interface which means interface can have a method with default implementation and static methods in Java 8. In a functional interface there may be one or more default methods/static methods but there should be only one abstract method. It is ok to have a functional interface like following.

 
@FunctionalInterface
public interface IMyFuncInterface {
  int func(int num1, int num2);
  // default method
  default int getValue(){
    return 0;
  }    
}

A functional interface can specify Object class public methods too in addition to the abstract method. That interface will still be a valid functional interface. The public Object methods are considered implicit members of a functional interface as they are automatically implemented by an instance of functional interface.

As example- This is a valid functional interface

@FunctionalInterface
interface IFuncInt {
  int func(int num1, int num2);
  // default method
  default int getValue(){
    return 0;
  }
  public String toString();
  public boolean equals(Object o);
}

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


Related Topics

  1. Lambda Expressions in Java 8
  2. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  3. Method Reference in Java 8
  4. Java Lambda Expression as Method Parameter
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Fail-Fast Vs Fail-Safe Iterator in Java
  2. How to Iterate a HashMap of ArrayLists of String in Java
  3. strictfp in Java
  4. static Import in Java With Examples
  5. Synchronization in Java - Synchronized Method And Block
  6. Deadlock in Java Multi-Threading
  7. Difference Between Checked And Unchecked Exceptions in Java
  8. Externalizable Interface in Java

Thursday, May 16, 2024

Tuple in Python With Examples

Tuple in Python is one of the sequence data type that can store a group of elements. Tuple is similar to Python list with one notable difference that the Tuple is immutable where as list is mutable.

Once a tuple is created you can’t modify its elements. So performing operations like insert(),remove(), pop(), clear() are not possible on tuples.

Some of the important points about Python Tuple are-

  1. A tuple can store elements of different types.
  2. Tuple maintains the insertion order. Elements are inserted sequentially and you can iterate them in the same order.
  3. Tuple is immutable. So, it is not possible to change content of a tuple.
  4. Tuples can be indexed (both positive and negative) and sliced.

In this article we’ll see some of the features of the Python tuples with examples, methods in Tuple and functions that can be used with tuple.


Creating a tuple

1. In Python tuple is created by grouping elements with in parenthesis (), where the elements are separated by comma. It is the preferred way and also necessary in some scenarios.

# empty tuple
t = ()
print(t)

# tuple with items having different types
t = (12, 54, 'hello!')
print(t)

# tuple containing lists
t = ([1, 2, 3], [4, 5, 6])
print(t)

Output

()
(12, 54, 'hello!')
([1, 2, 3], [4, 5, 6])

Here note that though Tuple itself is immutable but it can contain mutable objects like list.

2. When a tuple with one item is constructed value should be followed by a comma (it is not sufficient to enclose a single value in parentheses).

t = (1)
print(type(t))

t = (1,)
print(type(t))

Output

<class 'int'>
<class 'tuple'>

As you can see, in first assignment type of t is integer not tuple. In the second assignment when value is followed by comma, the type of t is tuple.

3. You can also create a tuple using tuple() type constructor. An iterable can be passed as an argument to create a tuple, if no argument is passed then an empty tuple is created.

t = tuple()
print(t)
print(type(t))

Output

()
<class 'tuple'>

When argument is passed-

#Tuple as argument
t = tuple((1,2,3)) 
print(t)
print(type(t))

#List as argument
t = tuple([1, "Test", 4.56])
print(t)
print(type(t))

Output

(1, 2, 3)
<class 'tuple'>
(1, 'Test', 4.56)
<class 'tuple'>

Tuple packing and unpacking

Tuple can also be created without using parenthesis, it is known as tuple packing.

t = 3, 4, 'Hello'
print(t)
print(type(t))

Output

(3, 4, 'Hello')
<class 'tuple'>

You can also do tuple unpacking by assigning tuple items to variables, unpacking requires that there are as many variables on the left side of the equals sign as there are elements in the sequence.

#packing
t = 3, 4, 'Hello'
print(t)
print(type(t))

#unpacking
x, y, z = t
print('x',x)
print('y',y)
print('z',z)

Output

(3, 4, 'Hello')
<class 'tuple'>
x 3
y 4
z Hello

Accessing tuple elements using index

Tuple in python uses index starting from 0 to (tuple_length-1), it also uses negative indexing which starts at -1 from the end (right most element) and goes till tuple_length.

Here is an example showing tuple indexing for the stored elements.

To access an element of the tuple you can pass the corresponding index in the square brackets. For example to access the 5th element in a tuple you will pass tuple[4], as index starts from 0.

t = (2, 3, 6, 7, 9)
# 1st element
print(t[0])

#last element
print(t[4])

#last element
print(t[-1])

#first element
print(t[-5])

Output

2
9
9
2

Trying to pass index beyond the index range of the tuple results in ‘index error’. For example here is a tuple having 5 elements so index range for the tuple is 0..4, trying to access index 5 results in an error.

t = (2, 3, 6, 7, 9)
print(t[6])

Output

IndexError: tuple index out of range

Slicing a tuple

Just like string slicing you can do tuple slicing too which returns a new tuple.

Format of tuple slicing is as follows-

Tupleobject[start_position: end_position: increment_step]
  • start_position is the index from which the slicing starts, start_position is included.
  • end_position is the index at which the tuple slicing ends, end_position is excluded.
  • increment_step indicates the step size. For example if step is given as 2 then every alternate element from start_position is accessed.

All of these parameters are optional, if start_position is not specified then the slicing starts from index 0. If end_position is not specified then the slicing ends at list_length – 1 (last index). If increment_step is not specified then increment step is 1 by default.

t = [2, 4, 6, 8, 10]
print(t[1:len(t):2]) #[4, 8]


t = [2, 4, 6, 8, 10]
print(t[::])#[2, 4, 6, 8, 10]
print(t[-3:])#[6, 8, 10]

Methods in tuple

Tuples provide the following two methods-

  • count(x)- Returns the number of items x
  • index(x)- Returns the index of the first item that is equal to x

Functions that can be used with tuple

  • len- The len() function returns the number of items of a sequence
  • min- The min() function returns the minimum element in a sequence
  • max- The max() function returns the maximum element in a sequence
  • sorted- Return a new sorted list from the items in iterable.

Operators used with tuples

Tuples can be used with the following operators which result in a creation of new tuple.

  • + (concatenation)
  • * (replication)
  • [] (slice)

Iterating a tuple

You can iterate all elements of a tuple using for or while loop.

1. Using for loop

t = [3, 1, 9, 2, 5]
for i in t:
  print(i)

Output

3
1
9
2
5

2. Using while loop

t = [3, 1, 9, 2, 5]
i = 0;
while i < len(t):
  print(t[i])
  i += 1

Output

3
1
9
2
5

del keyword with tuple

Since tuple is immutable so elements can’t be modified or removed from a tuple but tuple itself can be deleted entirely using del keyword along with tuple instance.

t = [3, 1, 9, 2, 5]

print(t)
del t
print(t)

Output

[3, 1, 9, 2, 5]
   print(t)
NameError: name 't' is not defined

Second print(t) statement results in an error as tuple t is already deleted.

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

>>>Return to Python Tutorial Page


Related Topics

  1. Named Tuple in Python
  2. List Comprehension in Python With Examples
  3. String Length in Python - len() Function
  4. Python Functions : Returning Multiple Values
  5. Constructor in Python - __init__() function

You may also like-

  1. Python while Loop With Examples
  2. Multiple Inheritance in Python
  3. Installing Anaconda Distribution On Windows
  4. Python Program to Display Fibonacci Series
  5. Java Multithreading Interview Questions And Answers
  6. Dependency Injection in Spring Framework
  7. String in Java Tutorial
  8. Volatile Keyword in Java With Examples

Thursday, May 2, 2024

Java ReentrantLock With Examples

java.util.concurrent.locks package has added support for locks, which provides an alternative to using Synchronized in Java in scenarios where we need to control access to a shared resource. In this post we'll talk about one of the concrete implementation of the lock interface called ReentrantLock in Java. There is another implementation ReentrantReadWriteLock which is implementation of ReadWriteLock interface.

ReentrantLock was added in Java 5 along with other concurrent features like CyclicBarrier, ConcurrentHashMap, CopyOnWriteArrayList with in java.util.Concurrent package, to develop concurrent applications.


What is ReentrantLock and why needed

ReentrantLock class in Java is a concrete implementation of the Lock interface which is present in java.util.concurrent.locks package. One question which comes to mind is why this separate functionality for locking is needed when there already is Synchronized keyword in Java which provides the same functionality.

As you must be knowing every object created in Java has one mutually exclusive lock associated with it. When you are using synchronized you are using that lock implicitly (with no other feature) whereas when you are using any of the lock implementation (like ReentrantLock) you are using that lock explicitly. Which means there are methods like lock() to acquire the lock and unlock() to release the lock. Along with that ReentrantLock in Java provides many other features like fairness, ability to interrupt and a thread waiting for a lock only for a specified period.

According to the Java docs "ReentrantLock is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities."

Why is it called ReentrantLock

It is called ReentrantLock as there is an acquisition count associated with the lock which means when you use lock() method to acquire a lock and you get it then the acquisition count is 1.

A Reentrant lock will also allow the lock holder to enter another block of code with the same lock object as thread already owns it. In that case, if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. Let's see it with an example to make it clear-

Here two threads are created. In the run method of the thread class methodA() is called which uses the same lock object to control access. So you will see two things here-

  • Whichever thread acquires the lock will also be able to access methodA() critical section as it already holds the lock. Only thing is acquisition count will become 2.
  • Since in the methodA(), unlock() method is not used to release the lock (remember we need to release it twice as acquisition count is 2). So another thread will never get a chance to acquire a lock.
public class ReentrantDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Display("Thread-1", rLock));
    Thread t2 = new Thread(new Display("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

class Display implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Display(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Display run method, thread " + threadName + 
     " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      methodA();
    } finally{
      lock.unlock();
    }        
  }
    
  public void methodA(){
    System.out.println("In Display methodA, thread " + threadName + 
      " is waiting to get lock");
    //try {        
      lock.lock();      
      System.out.println("Thread " + threadName + "has got lock");
      System.out.println("Count of locks held by thread " + threadName + 
       " - " + lock.getHoldCount());
      // Not calling unlock
      /*} finally{
      lock.unlock();
    }*/
  }    
}

Output

starting threads 
In Display run method, thread Thread-1 is waiting to get lock
In Display run method, thread Thread-2 is waiting to get lock
Thread Thread-1has got lock
In Display methodA, thread Thread-1 is waiting to get lock
Thread Thread-1has got lock
Count of locks held by thread Thread-1 - 2

Here it can be seen that both thread starts and Thread-1 acquires a lock, Thread-1 will acquire the same lock again in methodA() but there it is not released. You can notice the method lock.getHoldCount() which gives the count of holds on this lock by the current thread. Since unlock() method is not called so lock is never released that is why Thread-2 never gets a chance to acquire a lock. You can see it never goes beyond this message "In Display run method, thread Thread-2 is waiting to get lock".

Note that in different runs thread which acquires a lock may vary.

Now let's correct the code and use the unlock() method to release the lock and see what happens.

public class ReentrantDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Display("Thread-1", rLock));
    Thread t2 = new Thread(new Display("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

class Display implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Display(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Display run method, thread " + threadName + 
     " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      methodA();
    } finally{
      lock.unlock();
    }      
  }
    
  public void methodA(){
    System.out.println("In Display methodA, thread " + threadName 
     + " is waiting to get lock");
    //acquiring lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + "has got lock");
      System.out.println("Count of locks held by thread " + threadName 
       + " - " + lock.getHoldCount());
    } finally{
      lock.unlock();
    }
  }  
}

Output

starting threads 
In Display run method, thread Thread-1 is waiting to get lock
In Display run method, thread Thread-2 is waiting to get lock
Thread Thread-1has got lock
In Display methodA, thread Thread-1 is waiting to get lock
Thread Thread-1has got lock
Count of locks held by thread Thread-1 - 2
Thread Thread-2has got lock
In Display methodA, thread Thread-2 is waiting to get lock
Thread Thread-2has got lock
Count of locks held by thread Thread-2 - 2

Now both threads are able to run as the locks are properly release after acquiring.

Convention while using ReentrantLock in Java

If you had noticed one thing in the above code lock.lock() method is always called before the try block. When you are using Reentrantlock in Java, it is a recommended practice to always immediately follow a call to lock with a try block.

If you will call lock() method with in the try block and some thing goes wrong while acquiring the lock finally block will still be called and there you will have lock.unlock() method. So you will end up unlocking the lock which was never acquired and that will result in IllegalMonitorStateException, that’s why it is recommended to call lock() method before try block.

At the same time you do want to unlock the acquired lock if something goes wrong after acquiring the lock, that is why immediately follow a call to lock with try block.

Features of ReentrantLock in Java

ReentrantLock provides many features like fairness, ability to interrupt and a thread waiting for a lock only for a specified period. Let's have a look at some of these features.

  1. Fairness- ReentrantLock has one constructor which takes boolean value as an argument. That lets you choose whether you want a fair or an unfair lock depending upon whether the boolean value is true or false. A fair lock is one where the threads acquire the lock in the same order they asked for it; whereas in case of an unfair lock a thread can sometimes acquire a lock before another thread that asked for it first.
  2. public ReentrantLock(boolean fair)
    
  3. Lock interruptibly- ReentrantLock provides a method lockInterruptibly, where the thread acquires a lock if it is not interrupted.
    public void lockInterruptibly() throws InterruptedException
     
  4. Ability to check if the lock is being held- ReentrantLock in Java provides ability to check if the lock is already being held using tryLock() method.

    tryLock()- Acquires the lock only if it is not held by another thread at the time of invocation.

    tryLock(long timeout, TimeUnit unit) - Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.

  5. Some of the other methods in ReentrantLock class are as follows-
    • getHoldCount()- Queries the number of holds on this lock by the current thread.
    • getWaitingThreads(Condition condition) - Returns a collection containing those threads that may be waiting on the given condition associated with this lock.
    • isHeldByCurrentThread()- Queries if this lock is held by the current thread.
    • isLocked()- Queries if this lock is held by any thread.

Drawbacks of ReentrantLock in Java

  1. Need to wrap lock acquisitions in a try/finally block and release the lock in finally block. Otherwise, if the critical section code threw an exception, the lock might never be released.
  2. Need to call unlock() method explicitly. Forgetting to do that will result in lock never getting released which will create a lots of problem and make it very hard to detect performance problems.
    With synchronization, the JVM ensures that locks are automatically released.

ReentrantLock Java example code

Let us see one more example of Reentrant lock where a resource is shared between two threads and the access is controlled using locks.

Thread.sleep is used to induce some delay, in that case also another thread won't break in. Only when the unlock() method is called and the lock is released other thread gets a chance.

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {
  public static void main(String[] args) {
    ReentrantLock rLock = new ReentrantLock();
    Thread t1 = new Thread(new Counter("Thread-1", rLock));
    Thread t2 = new Thread(new Counter("Thread-2", rLock));
    System.out.println("starting threads ");
    t1.start();
    t2.start();
  }
}

// Shared class for threads
class SharedResource{
  static int count = 0;
}

class Counter implements Runnable {
  private String threadName;
  ReentrantLock lock;
  Counter(String threadName, ReentrantLock lock){
    this.threadName = threadName;
    this.lock = lock;
  }
  @Override
  public void run() {
    System.out.println("In Counter run method, thread " + threadName 
    + " is waiting to get lock");
    // acquiring the lock
    lock.lock();
    try {
      System.out.println("Thread " + threadName + " has got lock");
      SharedResource.count++;
      System.out.println("Thread " + threadName + 
       " Count " + SharedResource.count);
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } finally{
      System.out.println("Thread " + threadName 
       + " releasing lock");
      // releasing the lock
      lock.unlock();
    }    
  }
}

Output

starting threads 
In Counter run method, thread Thread-1 is waiting to get lock
In Counter run method, thread Thread-2 is waiting to get lock
Thread Thread-1 has got lock
Thread Thread-1 Count 1
Thread Thread-1 releasing lock
Thread Thread-2 has got lock
Thread Thread-2 Count 2
Thread Thread-2 releasing lock

Points to remember

  • ReentrantLock in Java is a reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods with some extended features.
  • Some of these features include fairness, ability to interrupt and a thread waiting for a lock only for a specified period.
  • Thread which is currently holding a lock can repeatedly enter the same lock, acquisition count increments as many times current thread acquires the same lock.
  • lock has to be released as many times as it has been acquired.
  • Failure to call unlock() as many times as the lock is acquired will result is lock not being released and the thread will continue to hold it.
  • unlock() method should be called in a finally block. Otherwise, if the critical section code threw an exception, the lock might never be released

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


Related Topics

  1. ConcurrentHashMap in Java With Examples
  2. Java StampedLock With Examples
  3. Difference Between CountDownLatch And CyclicBarrier in Java
  4. Java Phaser With Examples
  5. Java Concurrency Interview Questions And Answers

You may also like-

  1. Race Condition in Java Multi-Threading
  2. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  3. How to Remove Duplicate Elements From an ArrayList in Java
  4. How to Sort elements in different order in TreeSet
  5. Difference Between Comparable and Comparator in Java
  6. @FunctionalInterface Annotation in Java
  7. Java Stream API Tutorial
  8. Dependency Injection in Spring Framework