简体   繁体   中英

Always run a processing thread if a message queue is not empty

Whenever the server receives a message from a client, the message will be put in a queue. Multiple threads can input data in the queue, but only one thread should read/process from it at a time. As long as there are messages in the queue, the processing thread should be alive. How do I make this work?

If I put the processing logic in a synchronized method, and start a new thread calling this method for every request, won't it be a waste of resources having all those threads in memory, waiting their turn?

On the other hand, if I use a single processing thread, with each request trying to start it if it's not already running:

public void onMessage(String message) {
    addToQueue(message);
    synchronized (lock) {
        if (!processingThread.isAlive())
            processingThread.start();
    }
}

// processing thread
public void process() {
    while (true) {
        String message = queue.poll();
        synchronized (lock) {
            if (message == null)
                return;
        }
        // process message
    }
}

How can I make sure I don't run into this scenario:

  1. Processing thread polls the queue for the next element. It gets the shared lock and enters a synchronized block. It checks and sees the element it read from the queue is null , so the queue is empty. The thread releases the lock, but its isAlive flag hasn't been set to false yet.
  2. Client request arrives, adding a message in the queue. The receiving method gets the lock, and enters its synchronized block. The processing thread is still alive, so it doesn't need to be started. The method releases the lock.
  3. The processing thread has now released the lock and dies.

In this case, there will be one unprocessed message in the queue. Can this scenario happen? As the bold sentence suggests, can the lock be released before the thread dies?

This is a consumer/producer problem. There is no need to stop/start the processing thread (consumer). It can block, waiting for a message in the queue. The client threads (producers) fill the queue and notify() the consumer thread which unblocks, removes the message and waits again. Here is an example https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM