- I have a piece of code like:
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
TaskQueue q = new TaskQueue();
List<Thread> ts = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Thread t = new Thread(() -> {
try {
String s = q.getTask();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getId() + " is interrupted ");
return;
}
}, "tGet" + i);
t.start();
ts.add(t);
}
Thread add = new Thread(() -> {
for (int i = 0; i < 2; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
String s = "t-" + Math.random();
System.out.println(LocalTime.now() + " add element: " + s);
q.addTask(s);
}
}, "tAdd");
add.start();
add.join();
Thread.sleep(100);
for (Thread t : ts) {
t.interrupt();
}
System.out.println("main function end");
}
public class TaskQueue {
Queue<String> queue = new LinkedList<>();
public synchronized void addTask(String s) {
this.queue.add(s);
this.notifyAll();
}
public synchronized String getTask() throws InterruptedException {
while (queue.isEmpty()) {
this.wait();
}
return queue.remove();
}
}
What I expect is that, you see there is 3 threads
wait()
to get task in queue, but only 2 would be added, one per 5s, when first task is added,notifyAll()
is called and those 3 threads should begin to compete, trying to fetchthis
lock caused bysynchronized
key word, and their status should change fromWAITING
toBLOCKED
for a short period until one random thread successfully achieve the lock. However, the competition did not happen, and here is the thread state recorded using VisualVM:We can see that when the first task is added the
tGet2
achievethis
lock and these 3 threads , their status did not turn intoBLOCKED
, maybe theBLOCKED
period is extremly short so the profiler had no time to record?