Introduction
Java threads are stuck in BLOCKED or WAITING state preventing application progress. This guide provides step-by-step diagnosis and resolution with specific commands and code examples.
Symptoms
Typical symptoms and error messages when this issue occurs:
bash
"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f8b2c001000 nid=0x2a3b waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.example.MyClass.method(MyClass.java:42)Observable indicators: - Application logs show errors or exceptions - JVM crashes or becomes unresponsive - Related services may fail or timeout
Common Causes
- 1.Thread concurrency issues stem from:
- 2.Improper synchronization primitives usage
- 3.Race conditions in shared state access
- 4.Missing thread safety in collections
- 5.Incorrect thread pool configuration
Step-by-Step Fix
Step 1: Check Current State
bash
jstack <pid>Step 2: Identify Root Cause
bash
jcmd <pid> Thread.printStep 3: Apply Primary Fix
java
// Primary fix: update configuration
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
MyBean bean = new MyBean();
bean.setTimeout(30000);
return bean;
}
}Apply this configuration and restart the application.
Step 4: Apply Alternative Fix (If Needed)
java
// Alternative fix: use properties
# application.properties
app.timeout=30000
app.retry-count=3
app.enabled=trueRun load tests to verify thread safety under concurrent access.
Step 5: Verify the Fix
After applying the fix, verify with:
bash
jstack <pid> | grep -A 10 "BLOCKED\|WAITING"Expected output should show successful operation without errors.
Common Pitfalls
- Forgetting to unlock in finally block
- Using synchronized incorrectly
- Not handling InterruptedException
Best Practices
- Use ExecutorService instead of creating threads
- Always handle InterruptedException
- Use concurrent collections for shared state
Related Issues
- Java ThreadPoolExecutor Rejected Execution
- Java ConcurrentModificationException
- Java ThreadLocal Memory Leak