0
  • 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 fetch this lock caused by synchronized key word, and their status should change from WAITING to BLOCKED 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: enter image description here

  • We can see that when the first task is added the tGet2 achieve this lock and these 3 threads , their status did not turn into BLOCKED, maybe the BLOCKED period is extremly short so the profiler had no time to record?

Jayesslee
  • 67
  • 6

1 Answers1

0

I find that the moment is just too fast to catch so we can make it longer. Add sleep() so that the Blocked period can be more obvious:

public synchronized String getTask() throws InterruptedException {
    while (queue.isEmpty()) {
        this.wait();
    }
    Thread.sleep(2000);
    return queue.remove();
}

And make main thread sleep longer before interrupting:

Thread.sleep(5000);

enter image description here

According to this post:

https://stackoverflow.com/a/36449178/6812019

The state Monitor in VisualVM UI, it means Blocked

Jayesslee
  • 67
  • 6