javamultithreadingconcurrencyjava.util.concurrentjava-threads

Java ExecutorService:- Notify a thread to wake up when an event occurs


I have a Manager class to which multiple threads register themselves (used UUID to generate unique identifiers per requests), gives payload to process and get their corresponding responses from the manager. I am using java.util.concurrent.ExecutorService to launch multiple threads. Here is an implementation for testing my Manager functionality-

public class ManagerTest {
    public static void main(String[] args) {
        try {
            Manager myManager = new Manager();
            // Start listening to the messages from different threads
            myManager.consumeMessages();
            int num_threads = Integer.parseInt(args[0]);
            ExecutorService executor = Executors.newFixedThreadPool(num_threads);

            for (int i = 0; i < num_threads; i++) {
                // class implementation is given below
                Runnable worker = new MyRunnable(myManager);
                executor.execute(worker);
            }
            executor.shutdown();
            // Wait until all threads are finish
            while (!executor.isTerminated()) {

            }
            System.out.println("\nFinished all threads");

            myManager.closeConnection();

        } catch (IOException | TimeoutException e) {
            e.printStackTrace();
        }
    }
}

Here is the implementation of MyRunnable class

class MyRunnable implements Runnable {
    private Manager managerObj;
    public MyRunnable(Manager managerObj) {
        this.managerObj = managerObj;
    }

    @Override
    public void run() {     
        try {
            Random rand = new Random();
            int  n = rand.nextInt(35);
            String requestId = UUID.randomUUID().toString();
            managerObj.registerRequest(requestId, n);
            managerObj.publishMessage(requestId);
            // Want to avoid this while loop
            while( ! managerObj.getRequestStatus(requestId)){

            }
            int response = managerObj.getRequestResponse(requestId);
            // do something else
            managerObj.unregisterRequest(requestId);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The manager will process requests and depending on the payload the response of a request can take varying amount of time. Whenever manager gets the response it sets the requests status to true by calling this function setRequestStatus(requestId). After this the thread will exit from the while loop and continues its execution.

The code if working fine, but the thread is doing too much work then needed by continuously looping over the while loop until the condition is met.

Is their a way to make a thread sleep after sending the requests to the manager, and manager signals this thread to wake up when its response is ready.

Pardon me if this sounds too simple to someone, I am a newbie to java and java-threading interface.


Solution

  • What you are doing is a busy-spin-loop, and it is a very bad thing to do, because a) it consumes a full CPU core per thread, and b) it actually keeps the CPU busy, which means that it is stealing processing time from other threads that might have useful work to do.

    There is a number of ways you can solve this, I will list them from worst to best.