Implementing an operations queue

Implementing an operations queue involves a combination of two threading classes:

Together, these two classes create an operations queue for sending and receiving messages in a separate thread.

Operation

The Operation class defines an interface for operations performed in the OperationsQueue.

interface Operation {
    // Implement here the operation to be executed
    void execute();
}

OperationsQueue

The OperationsQueue class uses the Operation interface to execute operations serially in a separate thread. The operations are executed in the run method, which creates a Vector for a queue of operations and executes them as they are assigned.

To implement the OperationsQueue class:

  1. Create the OperationsQueue.java class file.

  2. Import the required classes.

    import java.util.*;
  3. Set OperationsQueue to implement Runnable, and create the required variables.

    class OperationsQueue implements Runnable {
    
        private volatile boolean running = true;
        private final Vector operations = new Vector();
  4. Create a new Thread and a queuing method for the upcoming operations.

        OperationsQueue() {
            // Notice that all operations will be done in another
            // thread to avoid deadlocks with GUI thread
            new Thread(this).start();
        }
    
        void enqueueOperation(Operation nextOperation) {
            operations.addElement(nextOperation);
            synchronized (this) {
                notify();
            }
        }
  5. Create a method for stopping the Thread and a while-loop to handle the queued operations.

        // stop the thread
        void abort() {
            running = false;
            synchronized (this) {
                notify();
            }
        }
    
        public void run() {
            while (running) {
                while (operations.size() > 0) {
                    try {
                        // execute the first operation on the queue
                        ((Operation) operations.firstElement()).execute();
                    } catch (Exception e) {
                        // Nothing to do. It is expected that each operations handle
                        // their own locally exception but this block is to ensure
                        // that the queue continues to operate
                    }
                    operations.removeElementAt(0);
                }
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // it doesn't matter
                    }
                }
            }
        }
    }

Now that you have implemented the operations queue, implement the functionality for creating and sending events