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. JavaScript Arrow Function With Examples
  4. 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

Wednesday, May 1, 2024

NodeJS Event Loop

In this tutorial we'll see what is an event loop in NodeJS and how does it help in writing asynchronous, non-blocking code.

JavaScript is single threaded

Before you go any further two important points you must know are-

  1. JavaScript is synchronous in nature.
  2. JavaScript is single threaded.

By extension NodeJS that uses V8 engine to run JavaScript can also be termed as synchronous and single threaded. For example if we have a JavaScript file as given below, code execution will happen line by line.

console.log('This is executed first');
function test(){
    console.log('In the function test')
}
//function call
test();
console.log('This is executed at the end');

On executing it output is-

This is executed first
In the function test
This is executed at the end

Asynchronous code in NodeJS

JavaScript gives you an option to write asynchronous code using callbacks where the callback function is called when the execution of the asynchronous code is finished. For example using setTimeout(), Promise or fs.readFile() in NodeJS.

With asynchronous code the execution of the code doesn't get blocked waiting for some processing to finish like I/O operation to read a file, network operation to fetch some data. Code execution can carry on with other tasks, once the asynchronous task is done, execution gets notified and then callback function can be executed with the result of the asynchronous operation.

For example in the following code fs.readFile() function is used to read a file asynchronously and setTimeout() function is used to execute code after some delay.

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

console.log('This is executed first');

setTimeout(() => {
    console.log('Displayed after delay of 10ms')
}, 10);

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....');

Output

This is executed first
Waiting for file to be read....
Hello from nodeJS
Displayed after delay of 10ms

Now you can see that the code lines are not executed one after the another. Even though setTimeout() function is written first but it has to be executed after 10ms so the execution doesn't block there but continue with the other function readFile(). Since fs.readFile() is also asynchronous so the execution goes to the next line and displays the message on the console. Once the file is read, then the callback function is called which displays the content of the file.

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

This is the callback function which is called with the file data and the error if there is one.

How does NodeJS manage the asynchronous operations and how are callbacks executed that's where event loop in NodeJS comes into picture.

Event Loop in NodeJS

It is the event loop in Node.js that allows Node.js to perform non-blocking I/O operations even though JavaScript is single-threaded. That is done by assigning asynchronous operations to the underlying operating system whenever possible.

Note that event loop is just a C program that is part of libuv- the C library that implements the Node.js event loop and all of the asynchronous behaviors of the platform.

Event Loop working explained

When Node.js starts, it initializes the event loop and processes the provided input script, if there are any asynchronous operations within the script those are pushed to the OS. Since most modern kernels are multi-threaded, they can handle multiple operations executing in the background.

When one of these operations (which are pushed to the OS to execute) completes, the kernel tells Node.js so that the appropriate callback may be added to the poll queue to eventually be executed.

The event loop is a loop that runs as long as your Node.js application is running. Event loop's order of operation can be divided into different phases, each phase has a FIFO queue of callbacks to execute.

When the event loop enters a given phase, it will perform any operations specific to that phase, then execute callbacks in that phase's queue until the queue has been exhausted or the maximum number of callbacks has executed. When the queue has been exhausted or the callback limit is reached, the event loop will move to the next phase, and so on.

Phases in event loop

NodeJS Event Loop
  1. timers- this phase executes callbacks scheduled by setTimeout() and setInterval().

    For example

    console.log('This is executed first');
    
    setTimeout(() => {
        console.log('Displayed after delay of 10ms')
    }, 10);
    

    In the given code callback function is this part-

    () => {
        console.log('Displayed after delay of 10ms')
    }
    
    Which has to be executed after delay of 10ms.

    This callback function is added to the queue of the timer phase and event loop will execute it after all the synchronous code is executed, delay of at least 10ms has occurred and call stack is empty.

  2. pending callbacks- This phase executes callbacks for some system operations such as types of TCP errors. Callbacks for these errors will be queued to execute in the pending callbacks phase.
  3. idle, prepare- Only used internally.
  4. poll- This phase is used to retrieve new I/O events and to execute I/O related callbacks. If the poll queue is not empty, the event loop will iterate through its queue of callbacks executing them synchronously until either the queue has been exhausted, or the system-dependent hard limit is reached.
  5. check- This phase invokes setImmediate() callbacks.
    setImmediate(() => {
        console.log('setImmediate callback');
    });
    
  6. close- Processes close callbacks. If a socket or handle is closed abruptly (e.g. socket.destroy()), the 'close' event will be emitted in this phase.

    For example-

    Server.js

    const net = require('net');
    const server = net.createServer((socket) => {
        socket.on('close', () => {
            console.log('Socket closed');
        });
    });
    
    server.on('connection', (stream) => {
        console.log('someone connected!');
    });
     
    server.listen(8000, () => {
        console.log('server bound');
    });
    

    client.js

    var net = require('net');
    var client = net.connect({port: 8000}, function() {
       console.log('connected to server!');  
       client.destroy();
    });
    

That's all for this topic NodeJS Event Loop. 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. How to Setup a Node.js Project
  3. NodeJS NPM Package Manager
  4. JavaScript Arrow Function With Examples

You may also like-

  1. Angular Access Control CanActivate Route Guard Example
  2. Checkbox in Angular Form Example
  3. Java Stream - boxed() With Examples
  4. Java Semaphore With Examples
  5. Reading File in Java Using Scanner
  6. Spring WebFlux Example Using Functional Programming - Spring Web Reactive
  7. Controlled and Uncontrolled Components in React
  8. Equality And Relational Operators in Java

Tuesday, April 30, 2024

Pre-defined Functional Interfaces in Java

We saw in the post Functional Interfaces in Java how you can create your own functional interface and also annotate it using @FunctionalInterface Annotation. Though it is not always required that you have to create your own functional interface for each scenario, Java has introduced a new package java.util.function that defines many general purpose pre-defined functional interfaces used by many Java libraries like Collection framework, Java Stream API and used by user code as well. In this post we’ll go through these built-in functional interfaces in Java so you have a good idea which functional interface to use in which context while using with Lambda expressions in Java.


Pre-defined functional interfaces categorization

Functional interfaces defined in java.util.function package can be categorized into five types-

  1. Consumer- Consumes the passed argument and no value is returned.
  2. Supplier- Takes no argument and supplies a result.
  3. Function- Takes argument and returns a result.
  4. Predicate- Takes argument and returns a boolean result (true or false).
  5. Operators- Functional interfaces categorized under Operator are specialized Function where the passed argument and result are of the same type.

Consumer functional interface

Consumer<T> represents a function that accepts a single input argument and returns no result. Consumer functional interface definition is as given below consisting of an abstract method accept() and a default method andThen()-

@FunctionalInterface
public interface Consumer<T> {
  void accept(T t);
  default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
  }
}

Following pre-defined Consumer functional interfaces are categorized as Consumer as all of these interfaces have the same behavior of consuming the passed value(s) and returning no result. You can use any of these based on number of arguments or data type.

  • BiConsumer<T,U>- Represents an operation that accepts two input arguments and returns no result.
  • DoubleConsumer- Represents an operation that accepts a single double-valued argument and returns no result.
  • IntConsumer- Represents an operation that accepts a single int-valued argument and returns no result.
  • LongConsumer- Represents an operation that accepts a single long-valued argument and returns no result.
  • ObjDoubleConsumer<T>- Represents an operation that accepts an object-valued and a double-valued argument, and returns no result.
  • ObjIntConsumer<T>- Represents an operation that accepts an object-valued and a int-valued argument, and returns no result.
  • ObjLongConsumer<T>- Represents an operation that accepts an object-valued and a long-valued argument, and returns no result.

Consumer functional interface Java example

In the example elements of List are displayed by using an implementation of Consumer functional interface.

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerExample {
  public static void main(String[] args) {
    Consumer<String> consumer = s -> System.out.println(s);
    List<String> alphaList = Arrays.asList("A", "B", "C", "D");
    for(String str : alphaList) {
      // functional interface accept() method called
      consumer.accept(str);
    }
  }
}

Output

A
B
C
D

Supplier functional interface

Supplier<T> represents a function that doesn't take argument and supplies a result. Supplier functional interface definition is as given below consisting of an abstract method get()-

@FunctionalInterface
public interface Supplier<T> {
  T get();
}

Following pre-defined Supplier functional interfaces are categorized as Supplier as all of these interfaces have the same behavior of supplying a result.

  • BooleanSupplier- Represents a supplier of boolean-valued results.
  • DoubleSupplier- Represents a supplier of double-valued results.
  • IntSupplier- Represents a supplier of int-valued results.
  • LongSupplier- Represents a supplier of long-valued results.

Supplier functional interface Java example

In the example Supplier functional interface is implemented as a lambda expression to supply current date and time.

import java.time.LocalDateTime;
import java.util.function.Supplier;

public class SupplierExample {
  public static void main(String[] args) {
    Supplier<LocalDateTime> currDateTime = () -> LocalDateTime.now();
    System.out.println(currDateTime.get());
  }
}

Function functional interface

Function<T,R> represents a function that accepts one argument and produces a result. Function functional interface definition is as given below consisting of an abstract method apply(), two default methods compose(), andThen() and a static method identity().

@FunctionalInterface
public interface Function<T, R> {

  R apply(T t);

  default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
  }

  default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
  }
  static <T> Function<T, T> identity() {
    return t -> t;
  }
}

Following pre-defined Function functional interfaces are categorized as Function as all of these interfaces have the same behavior of accepting argument(s) and producing a result.

  • BiFunction<T,U,R>- Represents a function that accepts two arguments and produces a result.
  • DoubleFunction<R>- Represents a function that accepts a double-valued argument and produces a result.
  • DoubleToIntFunction- Represents a function that accepts a double-valued argument and produces an int-valued result.
  • DoubleToLongFunction- Represents a function that accepts a double-valued argument and produces a long-valued result.
  • IntFunction<R>- Represents a function that accepts an int-valued argument and produces a result.
  • IntToDoubleFunction- Represents a function that accepts an int-valued argument and produces a double-valued result.
  • IntToLongFunction- Represents a function that accepts an int-valued argument and produces a long-valued result.
  • LongFunction<R>- Represents a function that accepts a long-valued argument and produces a result.
  • LongToDoubleFunction- Represents a function that accepts a long-valued argument and produces a double-valued result.
  • LongToIntFunction- Represents a function that accepts a long-valued argument and produces an int-valued result.
  • ToDoubleBiFunction<T,U>- Represents a function that accepts two arguments and produces a double-valued result.
  • ToDoubleFunction<T>- Represents a function that produces a double-valued result.
  • ToIntBiFunction<T,U>- Represents a function that accepts two arguments and produces an int-valued result.
  • ToIntFunction<T>- Represents a function that produces an int-valued result.
  • ToLongBiFunction<T,U>- Represents a function that accepts two arguments and produces a long-valued result.
  • ToLongFunction<T>- Represents a function that produces a long-valued result.

Function functional interface Java example

In the example a Function interface is implemented to return the length of the passed String.

import java.util.function.Function;

public class FunctionExample {
  public static void main(String[] args) {
    Function<String, Integer> function = (s) -> s.length();
    System.out.println("Length of String- " + function.apply("Interface"));
  }
}

Output

Length of String- 9

Predicate functional interface

Predicate<T> represents a function that accepts one argument and produces a boolean result. Abstract method in the Predicate functional interface is boolean test(T t).

Following pre-defined Predicate functional interfaces are categorized as Predicate as all of these interfaces have the same behavior of accepting argument(s) and producing a boolean result.

  • BiPredicate<T,U>- Represents a predicate (boolean-valued function) of two arguments.
  • DoublePredicate- Represents a predicate (boolean-valued function) of one double-valued argument.
  • IntPredicate- Represents a predicate (boolean-valued function) of one int-valued argument.
  • LongPredicate- Represents a predicate (boolean-valued function) of one long-valued argument.

Predicate functional interface Java Example

In the example a number is passed and true is returned if number is even otherwise odd is retuned.

import java.util.function.Predicate;

public class PredicateExample {
  public static void main(String[] args) {
    Predicate<Integer> predicate = (n) -> n%2 == 0;
    boolean val = predicate.test(6);
    System.out.println("Is Even- " + val);    
    System.out.println("Is Even- " + predicate.test(11));
  }
}

Output

Is Even- true
Is Even- false

Operator functional interfaces

Operator functional interfaces are specialized Function interfaces that always return the value of same type as the passed arguments. Operator functional interfaces extend their Function interface counterpart like UnaryOperator extends Function and BinaryOperator extends BiFunction.

Following pre-defined Operator functional interfaces are there that can be used in place of Function interfaces if returned value is same as the type of the passed argument(s).

  • BinaryOperator<T>- Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  • DoubleBinaryOperator- Represents an operation upon two double-valued operands and producing a double-valued result.
  • DoubleUnaryOperator- Represents an operation on a single double-valued operand that produces a double-valued result.
  • IntBinaryOperator- Represents an operation upon two int-valued operands and producing an int-valued result.
  • IntUnaryOperator- Represents an operation on a single int-valued operand that produces an int-valued result.
  • LongBinaryOperator- Represents an operation upon two long-valued operands and producing a long-valued result.
  • LongUnaryOperator- Represents an operation on a single long-valued operand that produces a long-valued result.
  • UnaryOperator<T>- Represents an operation on a single operand that produces a result of the same type as its operand.

UnaryOperator functional interface Java example

In the example UnaryOperator is implemented to return the square of the passed integer.

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
  public static void main(String[] args) {
    UnaryOperator<Integer> unaryOperator = (n) -> n*n;
    System.out.println("4 squared is- " + unaryOperator.apply(4));
    System.out.println("7 squared is- " + unaryOperator.apply(7));
  }
}

Output

4 squared is- 16
7 squared is- 49

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


Related Topics

  1. Exception Handling in Java Lambda Expressions
  2. Method Reference in Java
  3. How to Fix The Target Type of This Expression Must be a Functional Interface Error
  4. Java Stream API Tutorial
  5. Java Lambda Expressions Interview Questions And Answers

You may also like-

  1. Java Stream flatMap() Method
  2. Java Lambda Expression Callable Example
  3. Invoke Method at Runtime Using Java Reflection API
  4. LinkedHashMap in Java With Examples
  5. java.lang.ClassCastException - Resolving ClassCastException in Java
  6. Java String Search Using indexOf(), lastIndexOf() And contains() Methods
  7. BeanFactoryAware Interface in Spring Framework
  8. Angular Two-Way Data Binding With Examples

Monday, April 29, 2024

Checkbox in Angular Form Example

In this post we’ll see how to use check boxes in Angular form. We’ll see examples of adding check boxes to both template-driven and reactive form in Angular.

Checkbox in Reactive form Angular example

In this Angular Reactive form example we’ll have a form with two input fields for name and date (with a date picker for picking date) and a group of check boxes to select favorite exercises.

Friday, April 26, 2024

Printing Numbers in Sequence Using Threads Java Program

This post shows how you can print numbers in sequence using three threads in Java. If there are three threads thread1, thread2 and thread3 then numbers should be printed alternatively by these threads like this.

thread1 - 1
thread2 - 2
thread3 – 3
thread1 - 4
thread2 - 5
thread3 – 6
...
...
...

Print numbers in sequence using three threads in Java

While printing numbers in sequence using threads trick is to use modulo division to check which thread can print the number and which threads are to be blocked waiting.

Each thread is assigned one of the numbers 0, 1 and 2. Each number is divided by 3 (number of threads), remainder will be any one of these numbers 0, 1 or 2. That is what is checked; if (remainder = number assigned to thread) only then thread can work otherwise it goes into waiting state.

class SharedPrinter{
  int number = 1;
  int numOfThreads;
  int numInSequence;
  SharedPrinter(int numInSequence, int numOfThreads){
    this.numInSequence = numInSequence;
    this.numOfThreads = numOfThreads;
  }
  public void printNum(int result){
    synchronized(this) {
      while (number < numInSequence - 1) {
        while(number % numOfThreads != result){
          try {
            this.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        System.out.println(Thread.currentThread().getName() + " - " + number++);
        this.notifyAll();
      }
    }
  }
}
class SeqRunnable implements Runnable{
  SharedPrinter sp;
  int result;
  static Object sharedObj = new Object();
  SeqRunnable(SharedPrinter sp, int result){
    this.sp = sp;
    this.result = result;
  }
  @Override
  public void run() {
    sp.printNum(result);
  }
}
public class SeqNumber {
  final static int NUMBERS_IN_SEQUENCE = 10;
  final static int NUMBER_OF_THREADS = 3;
  public static void main(String[] args) {
    // Shared object
    SharedPrinter sp = new SharedPrinter(NUMBERS_IN_SEQUENCE, NUMBER_OF_THREADS);
    // Creating 3 threads
    Thread t1 = new Thread(new SeqRunnable(sp, 1), "Thread1");
    Thread t2 = new Thread(new SeqRunnable(sp, 2), "Thread2");
    Thread t3 = new Thread(new SeqRunnable(sp, 0), "Thread3");

    t1.start();
    t2.start();
    t3.start();
  }
}

Output

Thread1 - 1
Thread2 - 2
Thread3 - 3
Thread1 - 4
Thread2 - 5
Thread3 - 6
Thread1 - 7
Thread2 - 8
Thread3 - 9
Thread1 - 10

That's all for this topic Printing Numbers in Sequence Using Threads 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. How to Run Threads in Sequence in Java
  2. Print Odd-Even Numbers Using Threads And wait-notify Java Program
  3. Producer-Consumer Java Program Using ArrayBlockingQueue
  4. How to Create Deadlock in Java
  5. Race condition in Java multi-threading

You may also like-

  1. Converting String to Enum Type in Java
  2. Connection Pooling Using C3P0 in Java
  3. Java Program to Find First Non-Repeated Character in a Given String
  4. How to Convert String to Date in Java
  5. Java Multithreading Interview Questions And Answers
  6. How and Why to Synchronize ArrayList in Java
  7. BigDecimal in Java With Examples
  8. Introduction to Hadoop Framework

Thursday, April 25, 2024

FormGroup in Angular With Examples

Using FormGroup in Angular forms you can group FormControl instances and track the value and validity state of those instances as a group rather than for each individual FormControl instance. In this post we'll see example of using FormGroup with Angular template-driven form as well as with Reactive form.