A comprehensive collection of Java multithreading and concurrency examples demonstrating fundamental thread synchronization patterns, the producer-consumer problem, and advanced multi-queue systems.
This repository contains practical implementations of common concurrent programming patterns in Java, including:
- Basic thread synchronization using the
synchronizedkeyword - Thread coordination with
wait()andnotify()mechanisms - Producer-Consumer pattern implementations
- Multi-threaded systems with multiple queues and workers
concurrent-programming-java/
├── thread_synchronization/ # Basic thread synchronization
├── synchronized_display/ # Synchronized output display
├── producer_consumer/ # Producer-Consumer (Thread-based)
├── producer_consumer_runnable/ # Producer-Consumer (Runnable-based)
└── multi_queue_system/ # Advanced multi-queue system
Location: thread_synchronization/
Demonstrates basic thread synchronization where two threads execute sequentially without interference. Uses the synchronized keyword to ensure that only one thread can execute the critical section at a time.
Classes:
PrintDemo- Displays a countdown from 5 to 1ThreadDemo- Thread implementation with synchronized executionTestThread- Main class that launches two threads
Location: synchronized_display/
Shows how to prevent output interleaving when multiple threads write to the console simultaneously. Thread A implements Runnable while Thread B extends Thread, both displaying multi-line messages every 100ms.
Classes:
AfficheurSynchronise- Synchronized display managerThreadA- Runnable implementationThreadB- Thread extensionTestThreads- Main execution class
Location: producer_consumer/
Classic producer-consumer implementation using Thread inheritance. Features a fast producer (50ms delay) and a slow consumer (200ms delay) sharing a bounded message queue.
Classes:
FileDeMessages- Thread-safe message queue withsynchronized,wait(), andnotify()Producteur- Producer thread generating messagesConsommateur- Consumer thread processing messagesDistributeur- Main orchestrator
Key Concepts:
- Bounded buffer with maximum capacity
- Producer blocks when queue is full
- Consumer blocks when queue is empty
- Automatic synchronization and thread coordination
Location: producer_consumer_runnable/
Alternative implementation of the producer-consumer pattern using the Runnable interface instead of extending Thread. This approach provides better flexibility and follows composition over inheritance principles.
Advantages:
- Classes can extend other classes if needed
- Better separation of concerns
- More flexible thread management
Location: multi_queue_system/
Advanced implementation supporting multiple message queues with multiple producers and consumers working in parallel. Demonstrates scalable concurrent system design.
Features:
- N message queues
- X producer threads
- Y consumer threads
- Circular distribution of messages across queues
- Independent queue operations with per-queue synchronization
Default Configuration:
- 3 message queues
- 4 producer threads
- 2 consumer threads
- Queue capacity: 5 messages
- 10 messages per producer
- Java Development Kit (JDK) 8 or higher
- Terminal or command prompt
cd thread_synchronization
javac *.java
java thread_synchronization.TestThreadcd synchronized_display
javac *.java
java synchronized_display.TestThreadsThe program runs for 5 seconds, displaying alternating messages from threads A and B without interleaving.
cd producer_consumer
javac *.java
java producer_consumer.Distributeurcd producer_consumer_runnable
javac *.java
java producer_consumer_runnable.Distributeurcd multi_queue_system
javac *.java
java multi_queue_system.DistributeurEnsures that only one thread can execute a synchronized block or method at a time, preventing race conditions and ensuring thread safety.
Causes the current thread to wait until another thread invokes notify() or notifyAll() on the same object. The thread releases the lock while waiting.
Wakes up a single thread that is waiting on the object's monitor. Used to signal that a resource is now available.
Thread-safe collection used for storing messages. Provides synchronized access to elements, making it suitable for concurrent operations.
Separates the production and consumption of data, using a bounded buffer to decouple producers from consumers. Handles different processing speeds through blocking operations.
The multi-queue system demonstrates a thread pool approach where multiple worker threads (producers and consumers) operate on shared resources (message queues).
These patterns are commonly used in:
- Message processing systems
- Task scheduling and execution
- Event-driven architectures
- Data pipeline processing
- Resource pooling and management
- Asynchronous I/O operations
All implementations ensure thread safety through:
- Synchronized method access
- Proper use of wait/notify for thread coordination
- Thread-safe data structures (Vector)
- Bounded buffers to prevent resource exhaustion
- Proper exception handling for interrupted threads
If you encounter package errors, ensure you're in the correct directory when compiling.
- Ensure all
.classfiles are generated before running - Check that the main class name matches the package structure
- Verify Java version compatibility
By studying these implementations, you will understand:
- How to create and manage Java threads
- Thread synchronization mechanisms
- Producer-consumer problem and solutions
- Deadlock prevention techniques
- Scalable concurrent system design
- Thread communication patterns
This project is available for educational purposes.