How to make a Thread wait until an Array contains elements

I have two Threads Robot which both have an AssemblyLine lineIn and lineOut. The AssemblyLines are Arrays which contain elements. The lineOut from Robot 1 is the lineIn from Robot2, so they are “connected” via that AssemblyLine.

The Robots is picking up an element from the AssemblyLine lineIn, waiting a give amount of time and then putting the element down on the AssemblyLine lineOut.

How can I let the second robot wait or interrupt until the first robot put down the first element on the array?

That’s my solution, the problem is I heard Thread.sleep() + while() generates massive overhead:

public void run() {
    PrintedBoard printedBoard = null;
    while (lineIn.size() == 0) {
        try {
            Thread.sleep(1);
        } catch(InterruptedException ie) {}
    }

    while (printedBoard != PrintedBoard.STOPPER) {
        printedBoard = lineIn.pickUp();
        try {
            Thread.sleep(time);
        } catch (InterruptedException ie) {}
        lineOut.putDown(printedBoard);
    }
}

Answer

Explanation

I’ll give a minimal example that should showcase how it can be done.

The second robot needs some reference to where it can access the array or the property you want to check, for example a reference to the first robot. After that you create some while loop which checks the condition and yields CPU time, for example by sleeping.

Since arrays are always of fixed length you will need some additional logic that determines when a true value was entered into the array. Or you determine a special value that represents no value (like null). Alternatively you could use data-structures like List or Queue in the first place which already provide isEmpty methods.

public class FirstRobot() extends Thread {
    // Place for 10 objects
    private Object[] data = new Object[10];

    public boolean isDataEmpty() {
        // Check all entries for "null"
        for (Object entry : data) {
            if (entry != null) {
                return false;
            }
        }
        return true;
    }

    // Other thread stuff
}

public class SecondRobot extends Thread {
    private FirstRobot firstRobot;

    public SecondRobot(FirstRobot firstRobot) {
        // Second robot needs to access the "length" of the data
        this.firstRobot = firstRobot
    }

    @Override
    public void run() {
        // Wait for data to not be empty
        while (firstRobot.isDataEmpty()) {
            // Wait and try again afterwards
            Thread.sleep(100);
        }

        // Data is now not "empty"
    }
}

Notes

However as you might have noted the current implementation of isDataEmpty is slow as it checks every entry each time. You could easily improve on that by setting some boolean (a flag) to true once you add your first data value.

However a more appropriate data-structure would probably be a Queue. It can check isEmpty very fast and with poll you can get and remove the head element. And in your special case where multiple threads need to access the data-structure you probably want a thread-safe data-structure.

And note that there already is a data-structure called BlockingQueue (documentation) which, when trying to get an element, waits (blocks) until there is an element to fetch. It could be possible that this is exactly what you want.

Also note that you can approach this type of problem with several different approaches. I only showed one, you might research a bit for the individual parts of the solution and take a look at the alternatives.

Leave a Reply

Your email address will not be published. Required fields are marked *