Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Two Java Blocking Queues for Thread Communication

Tech 1

Implementing Two Java Blocking Queues for Thread Communication

Overview

Java provides robust blocking queue implementations to manage thread synchronization and communication. This example uses ArrayBlockingQueue and LinkedBlockingQueue to demonstrate sequential data transfer between two threads.

Implementation Steps

  1. Initialize two distinct blocking queues
  2. Create two worker threads: one produces elements to the first queue, and another consumes those elements and transfers them to the second queue
  3. Leverage built-in blocking behavior of put and take to handle synchronization automatically

Code Implementation

Step 1: Initialize Blocking Queues
// Fixed-capacity ArrayBlockingQueue with 15 slots
ArrayBlockingQueue<String> dataChannel1 = new ArrayBlockingQueue<>(15);
// Unbounded LinkedBlockingQueue
LinkedBlockingQueue<String> dataChannel2 = new LinkedBlockingQueue<>();
Step 2: Create Worker Threads
// Producer thread: sends data to dataChannel1
Thread dataProducer = new Thread(() -> {
    try {
        String message = "Processing Request #101";
        dataChannel1.put(message);
        System.out.println("Produced and sent to Channel 1: " + message);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        System.err.println("Producer thread interrupted");
    }
});

// Consumer-Forwarder thread: retrieves from dataChannel1 and sends to dataChannel2
Thread dataTransporter = new Thread(() -> {
    try {
        String receivedMessage = dataChannel1.take();
        System.out.println("Retrieved from Channel 1: " + receivedMessage);
        dataChannel2.put(receivedMessage);
        System.out.println("Forwarded to Channel 2: " + receivedMessage);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        System.err.println("Transporter thread interrupted");
    }
});

// Start both threads
dataProducer.start();
dataTransporter.start();

Blocking Mechanism Explanation

The put() method blocks if dataChannel1 reaches capacity, and take() blocks if dataChannel1 is empty, ensuring no race conditions or manual synchronization logic are needed.

Usage Scenario

This patteern is ideal for decoupling processing stages in multi-threaded aplications, such as pipeline architectures where raw data is first collected and then processed.

Key Differences Between the Two Queues

Feature ArrayBlockingQueue LinkedBlockingQueue
Capacity Fixed (must be specified) Optional (unbounded by default)
Underlying Structure Array-based (contiguous memory) Doubly linked list (dynamic nodes)
Performance Faster for bounded, predictable loads Better for unbounded, variable loads
Locking Strategy Single lock (for both put/take) Separate locks for put and take

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.