Friday, May 31, 2024

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. JavaScript Rest Parameter
  2. JavaScript let and const With Examples
  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!


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

NodeJS NPM Package Manager

In this article we'll see how to use npm in NodeJS to install packages which can then be used in the application.

NPM (https://www.npmjs.com/) is the standard package manager for Node.js. Using npm you can download and install dependencies of your project. It also acts as an online registry, with more than two million packages, npm Registry is the largest software registry in the world.

Check this post- How to Setup a Node.js Project to see how to setup a NodeJS project with a package.json file.

How to install NPM

When you install NodeJS, NPM package manager is also 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.

Installing packages using npm

To install any specific package you can use the following command

npm install <package-name>

You can control where and how the specified packages get saved by using some additional flags with npm install

-P, --save-prod: Package entry will appear in the dependencies section of the package.json file. You'll use this option if you want the installed package to be part of production build too. This is also the default option.

-D, --save-dev: Package entry will appear in the devDependencies section of the package.json file. You'll use this option if you want the installed package to be used during development only.

--no-save: With this option package will be installed but does not add the entry to the package.json file dependencies.

--save-optional: Installs and adds the entry to the package.json file optionalDependencies. If package's entry is in the optionalDependencies section that means dependency can be used if found, but installation doesn't fail if it cannot be found or fails to install. But it is your program's responsibility to handle the lack of the dependency.

--no-optional: Will prevent optional dependencies from being installed

For example, if you want to install ExpressJS

npm install express

Then you need to import 'express' package in your JS file

const express = require('express');

Note that when you use npm install command, packages are installed locally meaning installed to be used with in the specific application. Installed packages are kept in a node_modules directory which is present with in the node application for which packages are installed.

If you want to install packages globally use -g option with the install command. For example, if you want to install express module globally.

npm install express -g

Installing all dependencies

NPM can install all the dependencies of a project through the package.json file. If package.json file is already present with dependencies, devDependencies sections then npm install command will install all the packages required in the project.

Uninstalling packages

To uninstall a package from your project use the following command

npm uninstall <package name>

The package entry will also be removed from the list of dependencies in the package.json file.

Updating package

If you want to update a single package use the following command

npm update <package-name>

If you use the following command

npm update

npm will check all packages for a newer version that satisfies your versioning constraints.

That's all for this topic NodeJS NPM Package Manager. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Creating HTTP server in Node.js
  2. NodeJS Event Loop
  3. Node.js REPL
  4. JavaScript Arrow Function With Examples
  5. JavaScript Array and Object Destructuring

You may also like-

  1. How to Setup Angular
  2. Creating New Component in Angular
  3. Creating a New React Project - create-react-app
  4. Java ThreadLocal Class With Examples
  5. Java String Interview Questions And Answers
  6. java.lang.UnsupportedClassVersionError - Resolving UnsupportedClassVersionError in Java
  7. Dependency Injection in Spring Framework
  8. Spring Boot Microservices Introduction