Showing posts with label Java concurrency. Show all posts
Showing posts with label Java concurrency. Show all posts

Java Blocking Queues

java.util.concurrent.BlockingQueue is a Queue that supports operations that wait for the queue to become non-empty when retrieving and removing an element, and wait for space to become available in the queue when adding an element.

1. Thread safe
2. Allow duplicates
3. Not allowed null values

   

Types

  • ArrayBlockingQueue
  • DelayQueue
  • LinkedBlockingQueue
  • PriorityBlockingQueue
  • SynchronousQueue

Example

package com.vinod.test;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BlockingQueueExamples {
   public static void main(String[] args) throws InterruptedException, ExecutionException {
      BlockingQueue<String> bq = new ArrayBlockingQueue<String>(1000);
      ExecutorService exec = Executors.newFixedThreadPool(2);
      exec.submit(new ConsumerThread(bq));
      exec.submit(new ProducerThread(bq));

   }

}

class ProducerThread implements Callable<Object> {
   private BlockingQueue<String> blockingQueue;

   public ProducerThread(BlockingQueue<String> blockingQueue) {
      this.blockingQueue = blockingQueue;
   }

   public Object call() throws Exception {
      System.out.println("Producer Started:");
      Thread.sleep(1000);
      blockingQueue.put("vinod");
      Thread.sleep(1000);
      blockingQueue.put("vinod1");
      Thread.sleep(1000);
      blockingQueue.put("vinod2");
      return null;
   }

}

class ConsumerThread implements Callable<Object> {
   private BlockingQueue<String> blockingQueue;

   public ConsumerThread(BlockingQueue<String> blockingQueue) {
      this.blockingQueue = blockingQueue;
   }

   public Object call() throws Exception {
      System.out.println("Consumer Started:");
      System.out.println(blockingQueue.take());
      System.out.println(blockingQueue.take());
      System.out.println(blockingQueue.take());

      return null;
   }

}

Output

Consumer Started:
Producer Started:
vinod
vinod1
vinod2

Java 7 Fork and Join Example

Now a days parallel computing has become necessary for heavy or complex operations. Java 7 has introduced a Fork and Join framework which distributes the work across multiple cores and join them after completion which is the final result. These tasks or work is divided into small tasks until these task dont need any divide and all these tasks carried out separately. These task use a pool and task are divided according to that. The core classes which will be useful for fork and join are the ForkJoinPool and ForkJoinTask
Here is one simple example to print numbers based on the input size
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

/**
 *
 * This class helps to understand the feature of ForkJoinPool and ForkJoinTasks
 *
 * ForkJoinTask is an abstract class ,RecursiveAction and RecursiveTasks are the subclasses of ForkJoinTask class
 *
 * In case of return type required we need to use RecursiveTask
 *
 * In this example we used RecursiveAction and override its call() method to implement fork and join
 *
 * This is an example to print 1 to the given number
 *
 * The given number is less then 100 it will not split the task (fork)
 *
 * If the given number is 100 or greater than 100 it will split it in to two task (1 to 50 and 51 to 100)
 *
 * Finally join each task
 *
 *@authorvinod
 *
 */
public class ForkAndJoinExample {

public static void main(String[] args) {

ForkJoinPool fjpool = new ForkJoinPool(1);
RecursiveAction task = new PrintJob(100);
fjpool.invoke(task);

}
}

class PrintJob extends RecursiveAction {
private static final long serialVersionUID = 1L;
private int lines = 0;

public PrintJob(int lines) {
this.lines = lines;
}

@Override
protected void compute() {
if (lines < 100) {
print(1, lines, "single task");
} else {
PrintJob p1 = new PrintJob(lines);
p1.print(1, lines / 2, "task 1");
PrintJob p2 = new PrintJob(lines);
p2.print(lines / 2, lines, "task 2");
p1.fork();
p2.fork();
p1.join();
p2.join();
}
}

private void print(int start, int end, String taskname) {
for (int i = start; i <= end; i++) {
System.out.println("print job triggerd from " + taskname + " " + i);

}

}

}
Output
print job triggerd from task 1  31
print job triggerd from task 1 32
print job triggerd from task 1 33
print job triggerd from task 1 34
print job triggerd from task 1 35
print job triggerd from task 1 36
print job triggerd from task 1 37
print job triggerd from task 1 38
print job triggerd from task 1 39
print job triggerd from task 1 40
print job triggerd from task 1 41
print job triggerd from task 1 42
print job triggerd from task 1 43
print job triggerd from task 1 44
print job triggerd from task 1 45
print job triggerd from task 1 46
print job triggerd from task 1 47
print job triggerd from task 1 48
print job triggerd from task 1 49
print job triggerd from task 1 50
print job triggerd from task 2 50
print job triggerd from task 2 51
print job triggerd from task 2 52
print job triggerd from task 2 53
print job triggerd from task 2 54
print job triggerd from task 2 55
print job triggerd from task 2 56
print job triggerd from task 2 57
print job triggerd from task 2 58
print job triggerd from task 2 59
print job triggerd from task 2 60
print job triggerd from task 2 61
print job triggerd from task 2 62
print job triggerd from task 2 63
print job triggerd from task 2 64
print job triggerd from task 2 65
print job triggerd from task 2 66
print job triggerd from task 2 67
print job triggerd from task 2 68
print job triggerd from task 2 69
print job triggerd from task 2 70
print job triggerd from task 2 71
print job triggerd from task 2 72
print job triggerd from task 2 73
print job triggerd from task 2 74
print job triggerd from task 2 75
print job triggerd from task 2 76
print job triggerd from task 2 77
print job triggerd from task 2 78
print job triggerd from task 2 79
print job triggerd from task 2 80
print job triggerd from task 2 81
print job triggerd from task 2 82
print job triggerd from task 2 83
print job triggerd from task 2 84
print job triggerd from task 2 85
print job triggerd from task 2 86
print job triggerd from task 2 87
print job triggerd from task 2 88
print job triggerd from task 2 89
print job triggerd from task 2 90
print job triggerd from task 2 91
print job triggerd from task 2 92
print job triggerd from task 2 93
print job triggerd from task 2 94
print job triggerd from task 2 95
print job triggerd from task 2 96
print job triggerd from task 2 97
print job triggerd from task 2 98
print job triggerd from task 2 99
print job triggerd from task 2 100
print job triggerd from task 1 1
print job triggerd from task 1 2
print job triggerd from task 1 3
print job triggerd from task 1 4
print job triggerd from task 1 5
print job triggerd from task 1 6
print job triggerd from task 1 7
print job triggerd from task 1 8
print job triggerd from task 1 9
print job triggerd from task 1 10
print job triggerd from task 1 11
print job triggerd from task 1 12
print job triggerd from task 1 13
print job triggerd from task 1 14
print job triggerd from task 1 15
print job triggerd from task 1 16
print job triggerd from task 1 17
print job triggerd from task 1 18
print job triggerd from task 1 19
print job triggerd from task 1 20
print job triggerd from task 1 21
print job triggerd from task 1 22
print job triggerd from task 1 23
print job triggerd from task 1 24
print job triggerd from task 1 25
print job triggerd from task 1 26
print job triggerd from task 1 27
print job triggerd from task 1 28
print job triggerd from task 1 29
print job triggerd from task 1 30
print job triggerd from task 1 31
print job triggerd from task 1 32
print job triggerd from task 1 33
print job triggerd from task 1 34
print job triggerd from task 1 35
print job triggerd from task 1 36
print job triggerd from task 1 37
print job triggerd from task 1 38
print job triggerd from task 1 39
print job triggerd from task 1 40
print job triggerd from task 1 41
print job triggerd from task 1 42
print job triggerd from task 1 43
print job triggerd from task 1 44
print job triggerd from task 1 45
print job triggerd from task 1 46
print job triggerd from task 1 47
print job triggerd from task 1 48
print job triggerd from task 1 49
print job triggerd from task 1 50

Thread safe implementation of Queue (ConcurrentLinkedQueue) Example

An unbounded thread-safe queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is that element that has been on the queue the longest time. The tail of the queue is that element that has been on the queue the shortest time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue.

Example

package com.vinod.test;

import java.util.concurrent.ConcurrentLinkedQueue;

public class ConcurrentLinkedQueueExample {

    public static void main(String[] args) {
        ConcurrentLinkedQueue<String> orderQueue = new ConcurrentLinkedQueue<String>();
        orderQueue.add("order number 1");
        orderQueue.add("order number 2 premium");
        orderQueue.add("order number 3");
        orderQueue.add("order number 4");
        System.out.println("Order details after insertion");
        for (String orderDetail : orderQueue) {
            System.out.println(orderDetail);
            orderQueue.remove("order number 1");
        }
        System.out.println("priority order "+orderQueue.poll());
    }

}
   

Output

Order details after insertion

order number 1

order number 2 premium

order number 3

order number 4

priority order order number 2 premium

Thread safe TreeSet (ConcurrentSkipListSet) Example

Example

package com.vinod.concurrency;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
/**
 * Thread safe implementation for TreeSet.
 * @author vinod.kumaran
 *
 */
public class ConcurrentSkipListSetExample {
	public static void main(String args[]) {
		Set<String> treeSet = new ConcurrentSkipListSet<String>();
		treeSet.add("sunday");
		treeSet.add("monday");
		treeSet.add("tuesday");
		Iterator<String> treeSetIterator = treeSet.iterator();
		while (treeSetIterator.hasNext()) {
			String value = treeSetIterator.next();
			treeSet.add("wednesday");
		}
		System.out.println(treeSet);
	}
}

Output



[monday, sunday, tuesday, wednesday]


Thread Safe TreeMap (ConcurrentSkipListMap) Example

TreeMap is not thread safe and in case two threads are trying to modify the same object it will throw java.util.ConcurrentModificationException.
java.util.concurrent.ConcurrentSkipListMap is the implementation for Thread safe TreeMap and it will keep the natural ordering.

Example

package com.vinod.concurrency;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
public class ConcurrentSkipListMapExample {
	public static void main(String[] args) {
		// Map<String, String> treeMap = new TreeMap<String, String>();
		Map<String, String> treeMap = new ConcurrentSkipListMap<String, String>();
		treeMap.put("1", "sunday");
		treeMap.put("2", "monday");
		treeMap.put("3", "tuesday");
		for (Map.Entry entry : treeMap.entrySet()) {
			System.out.println(entry.getKey());
			treeMap.remove("3");
		}
		System.out.println(treeMap);
	}
}

Output



1
2
{1=sunday, 2=monday}


Thread Safe LinkedList (ConcurrentLinkedDeque) Example

java.util.concurrent.ConcurrentLinkedDeque is the thread safe implementation for LinkedList. This is same as LinkedList except the thread safe feature. Here is one example to add and remove items in ConcurrentLinkedDeque. If we are using this example with LinkedList it will throw ConcurrentModification Exception.

Example

package com.vinod.concurrency;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
 * Thread safe implementation of linked list.
 * 
 * @author vinod.kumaran
 *
 */
public class ConcurrentLinkedDequeExample {
	public static void main(String[] args) {
		ConcurrentLinkedDeque<String> linkedList = new ConcurrentLinkedDeque<String>();
		// List<String> linkedList = new LinkedList<String>();
		linkedList.add("sunday");
		linkedList.add("monday");
		linkedList.add("tuesday");
		for (String s : linkedList) {
			System.out.print(s + "->");
			linkedList.remove("sunday");
		}
		System.out.println(linkedList);
	}
}

Output



sunday->monday->tuesday->[monday, tuesday]



CopyOnWriteArraySet (Thread safe HashSet) Example

CopyOnWriteArraySet is a thread safe Set implementation and it is suitable for applications in which set sizes generally stay small read only operations and needs to prevent interference among threads during traversal.

Example

package com.vinod.concurrency;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;
public class CopyOnArraySetExample {
	// ThreadSafe Set implemenation as part of java concurrency api
	public static void main(String[] args) {
		HashSet<String> al = new HashSet<String>();
		al.add("sunday");
		al.add("monday");
		al.add("tuesday");
		Iterator<String> alIterator = al.iterator();
		while (alIterator.hasNext()) {
			String value = alIterator.next();
			al.add("wednesday");
		}
		System.out.println(al);
		CopyOnWriteArraySet<String> coal = new CopyOnWriteArraySet<String>();
		coal.add("sunday");
		coal.add("monday");
		coal.add("tuesday");
		Iterator<String> coalIterator = coal.iterator();
		while (coalIterator.hasNext()) {
			String value = coalIterator.next();
			coal.add("wednesday");
		}
		System.out.println(coal);
	}
}

Output


Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
    at java.util.HashMap$KeyIterator.next(HashMap.java:841)
    at com.vinod.concurrency.CopyOnArraySetExample.main(CopyOnArraySetExample.java:17)


This exception is from HashSet iteration, during iteration we are trying to add values and it is throwing ConcurrentModificationException.
Comment below line and run it again.


//al.add("wednesday");


Output


[monday, sunday, tuesday]
[sunday, monday, tuesday, wednesday]

Java Priority Queue Example

Priority Queue introduced as part of Java 1.5 and it is an unbounded queue based on a priority heap.

Elements in the queues are in natural ordering or by a comparator provided by at queue construction time.

It does not allow null values.

Example:


Here is one simple example to create a PriorityQueue to store order details and our priority is to process premium orders first.

package com.vinod;

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;

public class PriorityQueueTest {

public static void main(String[] args) {

// Creating Priority Queue and inserting objects
Comparator<String> pqc = new PQueueComparator();
Queue<String> orderQueue = new PriorityQueue<String>(100, pqc);
orderQueue.add("order number 1");
orderQueue.add("order number 2 premium");
orderQueue.add("order number 3");
orderQueue.add("order number 4");
System.out.println("Order details after insertion");
for (String orderDetail : orderQueue) {
System.out.println(orderDetail);
}
System.out.println("priority order " + orderQueue.poll());
}

}

class PQueueComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
if (s1.length() < s2.length()) {
return 1;
}
if (s1.length() > s2.length()) {
return -1;
}

return 0;
}

}

Ouput:

Order details after insertion
order number 2 premium
order number 1
order number 3
order number 4
priority order order number 2 premium

Java Thread join() — Run Threads in a Specific Order

Java Thread join() — Run Threads in a Specific Order 

The join() method is one of the simplest yet most powerful ways to control thread execution order in Java.

By default, Java threads run asynchronously, meaning:

  • They start immediately

  • They run independently

  • Their execution order is not guaranteed

But in some use cases—such as sequential processing, workflow pipelines, scheduler tasks—you need Thread A → then Thread B → then Thread C.

This is where join() helps.


What Does join() Do? (Simple Explanation)

join() tells the current thread:

“Wait here until the other thread finishes.”

Example:
If t1.join() is called inside the main thread:

main thread waits → until t1 finishes → then continues

So you get guaranteed ordering.


Use Case: Run Threads in Sequence

We want:

Thread 1Thread 2Thread 3

Each thread must start only after the previous one completes.


Full Java Example — Using join()

ThreadJoinExample.java

package threading; /** * This example demonstrates how the Thread join() method works. * * Requirement: * - Thread 2 must start only after Thread 1 completes * - Thread 3 must start only after Thread 2 completes * * We use join() to ensure strict sequential execution. * * @author vinod */ public class ThreadJoinExample { public static void main(String[] args) { Thread t1 = new Thread(new MyThread1()); Thread t2 = new Thread(new MyThread2()); Thread t3 = new Thread(new MyThread3()); try { t1.start(); // Thread 2 will start only after completion of Thread 1 t1.join(); t2.start(); // Thread 3 will start only after completion of Thread 2 t2.join(); t3.start(); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyThread1 implements Runnable { public void run() { System.out.println("Thread1 Started"); } } class MyThread2 implements Runnable { public void run() { System.out.println("Thread2 Started"); } } class MyThread3 implements Runnable { public void run() { System.out.println("Thread3 Started"); } }

Output

Thread1 Started Thread2 Started Thread3 Started

Execution order is guaranteed.


How It Works (Visual Diagram)

main thread │ ├── t1.start() │── wait using t1.join() │ ├── t2.start() │── wait using t2.join() │ └── t3.start()

Timeline:

t1: ──────────────(done) t2: ──────────────(done) t3: ──────────────(done)

When Should You Use join()?

Use join() when you need deterministic ordering:

✔ Workflow steps

Step 1 → Step 2 → Step 3

✔ Dependent tasks

Database migration → Index rebuild → Service restart

✔ Blocking until background work completes

Render UI only after data loads

✔ Waiting for multiple threads (with join() on each)


Important Notes

  • join() blocks the current thread, not the target thread

  • join() can cause performance issues if overused

  • For large-scale concurrency, prefer ExecutorService or Virtual Threads


Interview Tip

Q: What is the difference between start() and run()?

  • start() → creates a new thread

  • run() → executes like a normal method in the same thread

join() only works with start().


Java Callable and Future Simple Example

 

🧵 Java Callable and Future – Simple Example

💡 Overview

In Java, the Callable and Future interfaces are part of the java.util.concurrent package and provide a more powerful alternative to the traditional Runnable interface.

Both Runnable and Callable are designed for classes whose instances can be executed by another thread — but with one key difference:

InterfaceReturns Result?Throws Checked Exception?
Runnable❌ No❌ No
Callable✅ Yes✅ Yes

So, if you need a thread to return a result or throw a checked exception, Callable is the right choice.


⚙️ Key Concepts

  1. Callable Interface

    • Similar to Runnable, but defines a method call() that can return a result and throw exceptions.

    • Signature:

      V call() throws Exception;
  2. ExecutorService

    • Manages a pool of worker threads.

    • Handles thread creation, task scheduling, and shutdown gracefully.

  3. Future Interface

    • Represents the result of an asynchronous computation.

    • Allows you to retrieve the result using future.get() once the task completes.


🧩 Example: Callable and Future in Action

1️⃣ File: CallableExample.java

package threading; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * Demonstrates the use of ExecutorService, Callable, and Future interfaces. * * <ul> * <li>Thread1 implements Callable and overrides call() to return the thread name.</li> * <li>ExecutorService uses a fixed thread pool to execute multiple tasks.</li> * <li>Future stores and retrieves the result returned by Callable.</li> * </ul> * * Author: Vinod Kariyathungal Kumaran */ public class CallableExample { public static void main(String[] args) throws InterruptedException, ExecutionException { // Create a fixed thread pool of 10 threads ExecutorService ex = Executors.newFixedThreadPool(10); Thread1 t1 = new Thread1(); // Submit the Callable task multiple times and print results for (int i = 0; i <= 10; i++) { Future<String> future = ex.submit(t1); System.out.println(future.get()); } // Shutdown the executor ex.shutdown(); } } /** * Thread1 implements Callable and returns the current thread's name. */ class Thread1 implements Callable<String> { @Override public String call() throws Exception { return Thread.currentThread().getName(); } }

🧾 Output

pool-1-thread-1 pool-1-thread-2 pool-1-thread-3 pool-1-thread-4 pool-1-thread-5 pool-1-thread-6 pool-1-thread-7 pool-1-thread-8 pool-1-thread-9 pool-1-thread-10 pool-1-thread-1

🧠 Explanation

  1. ExecutorService creates a pool of 10 threads.
    This means at most 10 threads can run concurrently.

  2. Each time we call ex.submit(t1), the executor picks an available thread from the pool and runs the task.

  3. The Future<String> returned by submit() is used to get the result from Thread1.call().

  4. The output shows that threads are reused by the executor (thread-1 appears again at the end).

 

Confusion Matrix + Precision/Recall (Super Simple, With Examples)

  Confusion Matrix + Precision/Recall (Super Simple, With Examples) 1) Binary Classification Setup Binary classification means the model p...

Featured Posts