Skip to content

feat(datastructures): add thread-safe bounded queue implementation#7428

Open
MD-Mushfiqur123 wants to merge 5 commits into
TheAlgorithms:masterfrom
MD-Mushfiqur123:add-thread-safe-queue
Open

feat(datastructures): add thread-safe bounded queue implementation#7428
MD-Mushfiqur123 wants to merge 5 commits into
TheAlgorithms:masterfrom
MD-Mushfiqur123:add-thread-safe-queue

Conversation

@MD-Mushfiqur123
Copy link
Copy Markdown

Describe your change:

  • Add an algorithm?
  • Fix a bug or typo in an existing algorithm?
  • Add or change doctests? -- Note: Please avoid changing both code and tests in a single pull request.
  • Documentation change?

Checklist:

  • I have read CONTRIBUTING.md.
  • This pull request is all my own work -- I have not plagiarized.
  • I know that pull requests will not be merged if they fail the automated tests.
  • This PR only changes one algorithm file. To ease review, please open separate PRs for separate algorithms.
  • All new Java files are placed inside an existing directory.
  • All filenames are in all lowercase characters with no spaces or dashes.
  • All functions and variable names follow Java naming conventions.
  • All new algorithms have a URL in its comments that points to Wikipedia or another similar explanation.
  • The build runs successfully with mvn clean verify.

Thread-Safe Queue (Producer-Consumer)

A blocking queue that supports multiple producers and consumers using ReentrantLock and Condition variables.

What This Adds

ThreadSafeQueue.java - Thread-safe bounded queue:

  • enqueue() - Blocking add to tail, waits when queue is full
  • dequeue() - Blocking remove from head, waits when queue is empty
  • offer() - Non-blocking add, returns false when full
  • poll() - Non-blocking remove, returns null when empty
  • size(), isEmpty(), isFull(), capacity() - State queries
  • Uses circular buffer for O(1) enqueue/dequeue operations
  • Supports multiple concurrent producers and consumers

ThreadSafeQueueTest.java - Comprehensive test suite (15 tests):

  • Basic enqueue/dequeue operations
  • Offer/poll non-blocking behavior
  • Null rejection validation
  • Invalid capacity rejection
  • Circular buffer wrap-around
  • Multiple producers single consumer concurrency
  • Single producer multiple consumers concurrency
  • Blocking behavior verification
  • Stress test with 8 concurrent threads

Algorithm

Uses a circular buffer with ReentrantLock and two Condition variables:

  • notFull - signaled when space becomes available
  • notEmpty - signaled when items are added
  • Producers await notFull when buffer is full
  • Consumers await notEmpty when buffer is empty
  • Signal opposite condition after each operation

Time: O(1) enqueue/dequeue | Space: O(n) bounded buffer

Reference

https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem

Implements a thread-safe blocking queue using ReentrantLock and
Condition variables for producer-consumer synchronization.

### What This Adds

**ThreadSafeQueue.java** - Thread-safe bounded queue:
- `enqueue()` - Blocking add to tail, waits when queue is full
- `dequeue()` - Blocking remove from head, waits when queue is empty
- `offer()` - Non-blocking add, returns false when full
- `poll()` - Non-blocking remove, returns null when empty
- `size()`, `isEmpty()`, `isFull()`, `capacity()` - State queries
- Uses circular buffer for O(1) enqueue/dequeue operations
- Supports multiple concurrent producers and consumers

**ThreadSafeQueueTest.java** - Comprehensive test suite:
- Basic enqueue/dequeue operations
- Offer/poll non-blocking behavior
- Null rejection validation
- Invalid capacity rejection
- Circular buffer wrap-around
- Multiple producers single consumer concurrency
- Single producer multiple consumers concurrency
- Blocking behavior verification
- Stress test with 8 concurrent threads

### Algorithm

Uses a circular buffer with ReentrantLock and two Condition variables:
- `notFull` - signaled when space becomes available
- `notEmpty` - signaled when items are added
- Producers await notFull when buffer is full
- Consumers await notEmpty when buffer is empty
- Signal opposite condition after each operation

Time: O(1) enqueue/dequeue | Space: O(n) bounded buffer

### Reference

https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
- testOfferPoll: Changed capacity from 3 to 2 so third offer correctly fails
- testMultipleProducersSingleConsumer: Removed startLatch, use dedicated
  consumer thread with synchronized results list for thread safety
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.68%. Comparing base (4b8099c) to head (b6998e1).

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #7428      +/-   ##
============================================
+ Coverage     79.63%   79.68%   +0.05%     
- Complexity     7241     7259      +18     
============================================
  Files           800      801       +1     
  Lines         23608    23672      +64     
  Branches       4646     4653       +7     
============================================
+ Hits          18800    18864      +64     
  Misses         4055     4055              
  Partials        753      753              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Checkstyle flagged UnusedImports violation for
org.junit.jupiter.api.Assertions.assertArrayEquals which was
not used in any test method.
…_NOT_SIGNALALL

SpotBugs flags all four Condition.signal() calls in ThreadSafeQueue as Medium
severity bugs (MDM_SIGNAL_NOT_SIGNALALL). In a multi-producer/multi-consumer
scenario, signal() wakes only one waiting thread, which can cause deadlock when
multiple producers or consumers are blocked on the same condition variable.
Using signalAll() ensures all waiting threads are notified and can re-check
their loop condition, preventing the lost-wakeup problem that occurs when a
single signal wakes a thread that cannot make progress.

This change affects enqueue(), dequeue(), offer(), and poll() methods where
notEmpty.signal() and notFull.signal() are replaced with notEmpty.signalAll()
and notFull.signalAll() respectively.
…oManyStaticImports

PMD flags TooManyStaticImports when more than 4 static imports are present.
The test file had 5 static imports from org.junit.jupiter.api.Assertions
(equals, assertFalse, assertNull, assertThrows, assertTrue) which exceeded
the default threshold. Replaced with regular import and Assertions.
prefix to eliminate the PMD violation while maintaining readability.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants