Bird
Raised Fist0

Online Auction System

LLDmediumInterview freq: medium
Choose your preparation mode4 modes available
๐ŸŽฏ
Design an Online Auction System - Bid, Timer, Winner, Reserve Price, Notification
40 min ยท medium
medium

Design a system where multiple users can place bids on items within a timed auction. Each auction has a reserve price that must be met for the item to be sold. The system must notify bidders about bid status and auction results. The auction timer must handle concurrent bids and determine the winner when time expires.

  • Each auction has a reserve price that must be met or exceeded for a sale.
  • Bids can arrive concurrently and must be processed atomically to avoid race conditions.
  • The auction timer counts down and closes bidding when time expires.
  • Notifications must be sent asynchronously to bidders about bid acceptance, rejection, and auction results.
  • The system must support multiple concurrent auctions.
๐Ÿ“‹
Guided Steps
1/5
Step 1
Define core domain entities and their relationships
Identify the main classes such as Auction, Bid, User, and Item. Decide which classes hold state and how they relate (composition, aggregation, association).
๐Ÿ’ก Hint
Use abstract classes if shared state and behavior exist; use enums for fixed categories like BidStatus. Model ownership with composition if lifecycle is tied.
abstract class Auction(item, reservePrice, bids) - abstract because it holds instance state and behavior; interface cannot hold fields in Java. Use composition for bids lifecycle owned by Auction.
Mid: Names classes and relationships. Senior: Explains why Auction is abstract due to shared mutable state and why composition is used to enforce lifecycle ownership.
โš ๏ธCommon Wrong Answer
Using interfaces for Auction and Bid leads to inability to hold instance state, forcing external state management and breaking encapsulation.
Step 2
Implement thread-safe bid placement
Design the method to place a bid ensuring atomicity and consistency when multiple threads bid concurrently.
๐Ÿ’ก Hint
Use synchronized method or block on placeBid(Bid bid) to atomically check current highest bid and update bids list. Consider volatile or AtomicReference for highest bid tracking.
public synchronized boolean placeBid(Bid bid) - synchronized to atomically check highest bid and update bids list, preventing race conditions where two threads read same highest bid and both accept lower bids.
Mid: Identifies synchronized method to prevent race. Senior: Traces thread interleaving where Thread 1 reads highestBid, context switch, Thread 2 reads same highestBid, both accept bids, violating auction rules.
โš ๏ธCommon Wrong Answer
Using unsynchronized placeBid leads to race conditions where multiple bids accepted out of order, causing inconsistent highest bid and incorrect winner.
Step 3
Design auction timer and winner determination
Create a timer mechanism that closes the auction after a fixed duration and determines the winner based on highest bid meeting reserve price.
๐Ÿ’ก Hint
Use ScheduledExecutorService to schedule auction close task. Mark auction state volatile to ensure visibility across threads. Winner determination logic must be atomic with auction close.
volatile AuctionState auctionState; ScheduledExecutorService schedules closeAuction() which atomically sets auctionState=ENDED and determines winner based on highest bid >= reservePrice.
Mid: Uses ScheduledExecutorService for timer. Senior: Explains volatile ensures visibility of auctionState changes across threads, preventing stale reads that could allow late bids after auction end.
โš ๏ธCommon Wrong Answer
Using non-volatile auctionState causes threads to see stale state, allowing bids after auction closed, violating auction rules.
Step 4
Implement notification system for bidders
Design how notifications are sent asynchronously to bidders about bid acceptance, rejection, and auction results.
๐Ÿ’ก Hint
Use Observer pattern with interface NotificationListener. Use ExecutorService to send notifications asynchronously. Avoid blocking auction threads during notification.
interface NotificationListener with method void notify(Notification n); Auction holds List<NotificationListener> and uses ExecutorService.submit(() -> listener.notify(n)) to send notifications asynchronously.
Mid: Implements Observer pattern for notifications. Senior: Explains ExecutorService decouples notification delivery from auction logic, preventing auction thread blocking and improving scalability.
โš ๏ธCommon Wrong Answer
Sending notifications synchronously inside placeBid blocks auction threads, reducing throughput and causing delays.
Step 5
Support multiple concurrent auctions
Ensure the system can handle multiple auctions running concurrently without interference.
๐Ÿ’ก Hint
Use separate Auction instances per item. Use thread-safe collections or synchronization within each Auction. Consider thread confinement or concurrent collections for bids.
Each Auction instance manages its own synchronized placeBid and volatile auctionState; no shared mutable state across auctions avoids cross-auction race conditions.
Mid: Uses separate Auction instances. Senior: Explains how synchronized methods and volatile fields within each Auction isolate concurrency, preventing interference between auctions.
โš ๏ธCommon Wrong Answer
Using static shared state for bids or auctionState causes cross-auction interference and race conditions.
๐Ÿ”Œ
API Design Challenge
Design the API endpoints and method signatures for placing bids, querying auction status, and subscribing to notifications in the Online Auction System.
  • Consider RESTful endpoints with clear resource naming, e.g., POST /auctions/{id}/bids to place a bid.
  • Use WebSocket or Server-Sent Events for real-time notifications to subscribed clients.
  • Design idempotent and thread-safe methods to handle concurrent bid placements.
๐Ÿ“Š
Scoring Rubric
โ–ผ Show
Must Have - 60%
  • abstract class Auction with instance state and composition of bids
  • synchronized placeBid method for atomic bid placement
  • volatile auctionState for cross-thread visibility
  • ScheduledExecutorService for auction timer
  • Observer pattern with asynchronous notifications
Good to Have - 30%
  • enum types for BidStatus and AuctionState
  • ExecutorService for async notification delivery
  • Clear lifecycle ownership: composition for bids, aggregation for users and items
Bonus - 10%
  • Use AtomicReference for highest bid optimization
  • Support bid increments and automatic outbidding
Using interface for Auction with mutable state - interfaces cannot hold instance fields in Java, breaking encapsulation and forcing external state management
Unsynchronized placeBid leads to race conditions and inconsistent highest bid, causing incorrect winner determination
Non-volatile auctionState causes threads to see stale state, allowing bids after auction closed, violating auction rules
โœ…
Model Answer
โ–ผ Reveal

The Online Auction System is designed with an abstract Auction class that holds mutable state such as item, reserve price, and bids. Thread safety is ensured by synchronizing the placeBid method to prevent race conditions. The auctionState field is volatile to guarantee visibility across threads. A ScheduledExecutorService manages the auction timer, closing the auction and determining the winner atomically. Notifications to bidders are sent asynchronously using the Observer pattern with NotificationListener interface and ExecutorService to avoid blocking auction threads. Multiple concurrent auctions are supported by isolating state within each Auction instance, avoiding shared mutable static state.

  • Use abstract class Auction to hold instance state and behavior; interfaces cannot hold fields in Java
  • Synchronize placeBid method to atomically check and update highest bid, preventing race conditions
  • Mark auctionState as volatile to ensure visibility of auction status changes across threads
  • Use ScheduledExecutorService to schedule auction close task that atomically sets auctionState to ENDED and determines winner
  • Implement Observer pattern with NotificationListener interface and use ExecutorService to send notifications asynchronously
  • Manage concurrency within each Auction instance to avoid cross-auction interference
  • abstract class Auction holds item, reservePrice, bids list - abstract due to shared mutable state; interface cannot hold instance fields in Java
  • Use synchronized boolean placeBid(Bid bid) to atomically check and update highest bid, preventing race conditions
  • volatile AuctionState auctionState ensures visibility of auction status changes across threads
  • ScheduledExecutorService schedules auction close task to enforce timed auction lifecycle
  • Observer pattern with NotificationListener interface decouples notification delivery
  • ExecutorService used to send notifications asynchronously, avoiding blocking auction threads
  • Each Auction instance manages its own concurrency, avoiding shared mutable static state
  • Use enum BidStatus and AuctionState for type safety and exhaustive switch checks
  • Composition relationship: Auction owns bids lifecycle; bids cannot exist independently
  • Aggregation relationship: Auction references Item and Users, which exist independently

Practice

(1/5)
1. A class has a private constructor and a static synchronized getInstance() method returning a single instance. Which OOP concept or pattern is applied here and why is this the correct use case?
easy
A. Singleton pattern ensuring only one instance exists with thread-safe access
B. Factory Method pattern to create multiple instances with controlled access
C. Builder pattern to construct complex objects step-by-step
D. Prototype pattern to clone existing instances efficiently

Solution

  1. Step 1: Identify the pattern from constructor and method

    The private constructor prevents external instantiation, and the static synchronized getInstance() method ensures a single instance is created and accessed safely across threads.
  2. Step 2: Eliminate other creational patterns

    Factory Method allows multiple instances, Builder focuses on stepwise construction, and Prototype clones objects; none enforce single instance with thread safety.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Private constructor + synchronized static method -> Singleton pattern [check]
Hint: Private constructor + static synchronized method -> Singleton [check]
Common Mistakes:
2. In a multi-threaded Chess game server, without synchronizing the makeMove() method, which exact sequence of thread interleaving causes two players to move simultaneously, violating turn order?
medium
A. Thread 1 reads current player as White, moves piece; Thread 2 reads current player as Black, moves piece simultaneously.
B. Thread 1 checks if it's White's turn -> true, context switch; Thread 2 checks if it's White's turn -> true; both proceed to move.
C. Thread 1 locks board, moves piece; Thread 2 waits but proceeds after unlock.
D. Thread 1 updates board state; Thread 2 reads stale board state but waits for turn.

Solution

  1. Step 1: Identify the check-then-act race condition

    Both threads read the turn state before either updates it, causing both to believe it's their turn.
  2. Step 2: Trace thread interleaving

    Thread 1 checks turn -> true, context switch before move; Thread 2 checks turn -> true, both move simultaneously, violating turn order.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap allows double move without synchronization [check]
Hint: Check turn then act without lock -> race condition [check]
Common Mistakes:
3. In the Hotel Management System, if the parkVehicle() method is not synchronized, which exact sequence of events between Thread 1 and Thread 2 causes double-booking of the same parking spot?
medium
A. Thread 1 checks spot availability -> true, context switch before marking occupied; Thread 2 checks availability -> true, both park simultaneously.
B. Thread 1 marks spot occupied, Thread 2 reads spot as occupied and waits indefinitely.
C. Thread 1 parks vehicle, Thread 2 waits until Thread 1 finishes, then parks another vehicle.
D. Thread 1 and Thread 2 both crash due to simultaneous access causing deadlock.

Solution

  1. Step 1: Identify the check-then-act race condition

    Without synchronization, Thread 1 reads spot as available and is preempted before marking it occupied.
  2. Step 2: Thread 2 also reads spot as available and proceeds to park, causing double-booking.

    This is the classic check-then-act gap causing race condition.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check availability -> true by both threads before marking occupied -> double-booking [check]
Hint: Check-then-act gap -> double-booking without synchronization [check]
Common Mistakes:
4. In the Wallet System, the transferFunds() method checks if the source account has sufficient balance before debiting and crediting the destination. Without synchronization, what exact sequence of Thread 1 and Thread 2 causes double spending (overdraft)?
medium
A. Thread 1 checks balance -> sufficient, context switch; Thread 2 checks balance -> sufficient; both debit, overdrawing account.
B. Thread 1 and Thread 2 both debit simultaneously after checking balance, causing negative balance.
C. Thread 1 credits destination before debiting source, allowing inconsistent state visibility to Thread 2.
D. Thread 1 and Thread 2 both wait on a lock, causing deadlock and no transfer.

Solution

  1. Step 1: Identify the check-then-act race condition

    Both threads read the balance before either updates it, so both see sufficient funds and proceed.
  2. Step 2: Trace interleaving causing overdraft

    Thread 1 checks balance -> sufficient, context switch before debit; Thread 2 checks balance -> sufficient, both debit, resulting in overdraft.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Check-then-act gap -> both threads see same balance -> double debit [check]
Hint: Check balance -> context switch -> both debit -> overdraft [check]
Common Mistakes:
5. The system must support ElectricCar vehicles needing ChargingSpot parking. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Add a boolean isElectric flag to Vehicle and ParkingSpot classes and update all compatibility checks.
B. Modify existing Vehicle and ParkingSpot classes to add electric-specific fields and logic.
C. Create a new ElectricVehicleManager class that handles electric cars separately, duplicating some logic.
D. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and subclassing allows extension without changing existing class code, respecting OCP.
  2. Step 2: Update compatibility externally

    Updating SpotCompatibility map outside existing classes avoids modifying their code, enabling new vehicle-spot matching.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Extend enums + subclass + external map update -> no existing class changes [check]
Hint: Extend enums + subclass + external map -> no existing class changes [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard