While this project uses mostly basic Java concepts and tools, the tools are used in an advanced way that raises the level to slightly above basic, perhaps to the intermediate level. The project uses a single-thread to simulate the operation of a pizza parlor. The simulation was inspired by this thread.

The code below is heavily commented so that further explanation should be unnecessary, but to prevent you reading the code to determine what it is or does, here's a summary copied from the existing comments:

demonstrates the use of a queue to accomplish events in simulation time
rather than real or scaled time. multi-threading is not used, because this
simulation is intended to be a precursor to a multi-threaded program, and
more than a single thread is not needed

concept: events are added to a queue ordered by their start times,
priorities, and event numbers. the simulation time begins at zero and
advances to each event's start time as the event is removed from the queue
and processed. as each event is processed, its start time and priority are
modified to reflect the next action and then returned to the queue if the
event is still in play or removed if it is not

Also noted in the comments is that the posted code will not run without the missing Event and OrderedEventQueue classes. The Event class implements Comparable to define the ordering of Event objects and is otherwise unremarkable. Even simpler is the OrderedEventQueue class that extends an ArrayList so that 3 simple methods could be added to both control and inspect the objects in the queue.

Questions/comments welcome.
import java.util.ArrayList;
import java.util.Random;
 
/**
 * File: PizzaParlorSimulation.java
 * Author: GregBrannon, April 2014
 *
 * inspired by this thread:
 * 
 * [url]http://www.javaprogrammingforums.com/whats-wrong-my-code/36975-elevator-simulation-event-time-not-clock.html#post144786[/url]
 *
 * demonstrates the use of a queue to accomplish events in simulation time
 * rather than real or scaled time. multi-threading is not used, because this
 * simulation is intended to be a precursor to a multi-threaded program, and
 * more than a single thread is not needed
 *
 * simulation rules, assumptions, etc.
 * - the simulation has 4 events: order, prepare, cook, and remove.
 * - each pizza order is an Event (my custom Event class) that is modified to
 *   be each of the other events as the simulation proceeds 
 * - the first pizza is ordered at time zero
 * - each subsequent pizza order arrives at intervals of 2 to 5 (inclusive)
 *       time units
 * - a pizza order event is assigned a random queue time of at least
 *       5 time units to a maximum of 8 time units 
 * - pizza preparation time is a random number of time units between 8 and 15
 * - the simulation will run for the number MAX_PIZZAS
 * - the time to bake a pizza is randomly chosen between 20 and 30 (inclusive)
 *       time units
 * - 4 pizzas can be cooking at once (set by the variable ovenSpace)
 * 
 * to avoid providing a total solution, the posted simulation code omits my
 * custom Event and OrderedEventQueue classes. ask for help if needed to
 * construct your own versions of these classes. the requirements
 * for both classes should be derivable from the posted code, except for the
 * queue's insertInOrder() method and the Event's compareTo() method that
 * it depends on. if there's any secret sauce, it's in those two methods
 * 
 * concept: events are added to a queue ordered by their start times,
 * priorities, and event numbers. the simulation time begins at zero and
 * advances to each event's start time as the event is removed from the queue
 * and processed. as each event is processed, its start time and priority are
 * modified to reflect the next action, and then returned to the queue or
 * removed, if the event has completed the final action
 * 
 * TODO add the option to specify the number of pizzas that can be in the
 * oven at a time by varying the variable ovenSpace
 */
public class PizzaParlorSimulation
{
    // instance variables
    private final boolean TEST;
    private int currentSimTime;
    private int orderNumber;
    private int pizzasInOven;
    private int ovenSpace;
    private int pizzasDelivered;
    private final int MAX_PIZZAS;
    private boolean acceptingOrders;
    private OrderedEventQueue<Event> orderedEventQueue;
    private Random random;
    private Event newEvent;
 
    // default constructor - used to initialize instance variables and then
    // start the simulation
    public PizzaParlorSimulation()
    {
        // a flag to indicate whether the simulation should run in the test
        // or production modes
        TEST = false;
 
        // initialize instance variables
        currentSimTime = 0;
        orderNumber = 0;
        pizzasInOven = 0;
        ovenSpace = 4;
        pizzasDelivered = 0;
        orderedEventQueue = new OrderedEventQueue<Event>();
        random = new Random( System.currentTimeMillis() );
        MAX_PIZZAS = 40;
        acceptingOrders = true;
 
        // start the simulation of ordering and baking pizzas
        makePizzaPies();
 
    } // end default constructor
 
    // a controller for the pizza demo
    private void makePizzaPies()
    {
        // continue the simulation until event queue is empty
        do
        {
            // add another pizza order to the queue if the simulation is still
            // accepting orders
            if ( acceptingOrders )
            {
                orderPizza();
            }
 
            // retrieve the next event from the event queue and process it,
            // updating the current simulation time with the event's start time
            processNextEvent();
 
            reportStatus();
        }
        while ( !orderedEventQueue.isEmpty() );
 
    } // end method makePizzaPies()
 
    // creates a pizza order event and adds it to the queue. prints a message
    // if the maximum number of orders have been accepted
    public void orderPizza()
    {
        // the first the pizza order arrives in the queue at time zero
        int eventStartTime = 0;
 
        // only allow number of pizza orders defined by MAX_PIZZAS
        if ( orderNumber < MAX_PIZZAS )
        {
            // in test mode, report the status of the simulation
            if ( TEST )
            {
                System.out.println( "Pizza order #" + orderNumber +
                        " is being accepted" );
            }
 
            // determine the pizza order's details
            // the start time for all pizzas after the first is the current
            // event time plus a random number between 2 and 5, inclusive
            if ( orderNumber > 0 )
            {
                eventStartTime = currentSimTime + random.nextInt( 4 ) + 2;
            }
 
            // the rest of the order's attributes . . .
            String eventName = "OrderPizza" + orderNumber;
            int eventNumber = orderNumber++;
 
            // set the time to process the order (minimum queue time)
            // a random number between 5 and 8
            int eventDuration = random.nextInt( 4 ) + 5;
 
            // the queue time for events is orderWaitTime + ovenWaitTime and
            // then increases each time the event must wait for a spot in the
            // oven
            int eventQueueTime = eventDuration;
 
 
            // the following is not used at the order stage
            // TODO (or at all yet)
            int eventEndTime = 0;
 
            // create the order and add it to the queue in order
            newEvent = new Event( eventName, eventNumber, eventStartTime,
                    eventDuration, eventQueueTime, eventEndTime );
 
            // set the new event's priority to 3 (the highest)
            newEvent.setEventPriority( 3 );
 
            orderedEventQueue.insertInOrder( newEvent );
        }
        else
        {
            System.out.
            println( "The pizza parlor is not accepting more orders." );
            acceptingOrders = false;
        }
 
    } // end method orderPizza()
 
    // retrieves the next event from the queue and processes it
    private void processNextEvent()
    {
        Event nextEvent = null;
 
        // take the first event from the queue
        if ( !orderedEventQueue.isEmpty() )
        {
            nextEvent = orderedEventQueue.remove( 0 );
        }
        else
        {
            System.out.println( "Simulation complete!" );
            return;
        }
 
        // advance the current time to the event's start time
        // (this will be zero for the first event but will advance after that)
        currentSimTime = nextEvent.getEventStartTime();
 
        // a message to monitor progress 
        System.out.println( "The name of the event being processed is: " +
                nextEvent.getEventName() );
 
        // if the event is an order . . .
        if ( nextEvent.getEventName().startsWith( "Order" ) )
        {
            // a message to monitor progress in TEST mode
            if ( TEST )
            {
                System.out.println( "Assembling pizza # " +
                        nextEvent.getEventNumber() + " before cooking at time " +
                        currentSimTime );
            }
 
            // set the time to prepare the pizza for the oven (build the pizza)
            // a random number between 8 and 15
            nextEvent.setEventDuration( random.nextInt( 7 ) + 8 );
 
            // add the next queue time to the total event queue time
            nextEvent.setEventQueueTime( nextEvent.getEventQueueTime() +
                    nextEvent.getEventDuration() );
 
            // set up the event to for its next step
            nextEvent.setEventName( "CookPizza" + nextEvent.getEventNumber() );
 
            // set the new event's priority to 2 (the middle)
            newEvent.setEventPriority( 2 );
 
            // set this event's next start time as the current time plus the
            // event's duration.  setting the event start time is the key to
            // simulating correctly
            nextEvent.setEventStartTime( currentSimTime + 
                    nextEvent.getEventDuration() );
 
            // return the event to the queue
            orderedEventQueue.insertInOrder( nextEvent );
        }
        // . . . or if it is to cook the pizza . . .
        else if ( nextEvent.getEventName().startsWith( "Cook" ) )
        {
            // this step is limited by the amount of oven space. to make the
            // simulation interesting, the user could be asked how many pizzas
            // can be cooked at a time before the simulation begins. the default
            // value is four, but that can be increased to see the effect of
            // cooking space to complete the desired number of pizzas
            if ( pizzasInOven < ovenSpace )
            {
                // a message to monitor progress in TEST mode
                if ( TEST )
                {
                    System.out.println( "Moving pizza # " +
                            nextEvent.getEventNumber() +
                            " into the oven at time " + currentSimTime );
                }
 
                // set the time to cook the pizza, a random number between
                // 20 and 30
                nextEvent.setEventDuration( random.nextInt( 11 ) + 20 );
 
                // add the next queue time to the total event queue time
                nextEvent.setEventQueueTime( nextEvent.getEventQueueTime() +
                        nextEvent.getEventDuration() );
 
                // set up the event to for its next step
                nextEvent.setEventName( "RemovePizza" + 
                        nextEvent.getEventNumber() );
 
                // set the new event's priority to 1 (the lowest)
                nextEvent.setEventPriority( 1 );
 
                // set this event's next start time as the current time plus the
                // event's duration.  setting the event start time is the key to
                // simulating correctly
                nextEvent.setEventStartTime( currentSimTime + 
                        nextEvent.getEventDuration() );
 
                // return the event to the queue
                orderedEventQueue.insertInOrder( nextEvent );
 
                // increment the number of pizzas in the oven
                pizzasInOven++;
            }
            else
            {
                // a message to monitor progress in TEST mode
                if ( TEST )
                {
                    System.out.
                        println( "The oven is full, must wait for room." );
                }
 
                // increment the event's start time and return it to the queue
                nextEvent.setEventStartTime( currentSimTime + 1 );
 
                // increment the event's total queue time
                nextEvent.
                    setEventQueueTime( nextEvent.getEventQueueTime() + 1 );
 
                orderedEventQueue.insertInOrder( nextEvent );
            }
        }
        // . . . or, finally, to remove the pizza from the oven . . .
        else if ( nextEvent.getEventName().startsWith( "Remove" ) )
        {
            // a message to monitor progress 
            System.out.println( "Removing pizza # " +
                    nextEvent.getEventNumber() + " from the oven at time " +
                    currentSimTime );
 
            // set the event's end time
            nextEvent.setEventEndTime( currentSimTime );
 
            // decrement the number of pizzas in the oven
            pizzasInOven--;
 
            // increment the number of pizzas delivered
            pizzasDelivered++;
        }
 
    } // end method processNextEvent()
 
    // report current simulation time, total pizzas ordered, total pizzas
    // delivered, pizza orders in queue, waiting for oven, in oven, total
    // queue time
    private void reportStatus()
    {
        /* this is a more compact message used to monitor the sim's progress
         * while debugging */
        if ( TEST )
        {
            System.out.println( "The current eventNumber:startTime:priority"
                    + ":duration of the events in the queue is: " );
            for ( int i = 0 ; i < orderedEventQueue.size() ; i++ )
            {
                System.out.print( orderedEventQueue.get( i ).
                        getEventNumber() + ":" );
                System.out.print( orderedEventQueue.get( i ).
                        getEventStartTime() + ":" );
                System.out.print( orderedEventQueue.get( i ).
                        getEventPriority() + ":" );
                System.out.print( orderedEventQueue.get( i ).
                        getEventDuration() + ", " );
            }
 
            System.out.println();
        }
 
        // TODO total queue time is a snapshot of the queue time for all events
        // currently in queue. further coding will be required to accumulate
        // all queue time that occurred during the entire simulation. care will
        //be required to ensure that queue time is not double counted
 
        else
        {
            // report the simulation's current results
            System.out.println( "\nAt simulation time: " + currentSimTime + 
                    ", the status is:" );
            System.out.println( "Total pizzas ordered: " + orderNumber );
            System.out.println( "Total items in the queue: " +
                    orderedEventQueue.size() );
            System.out.println( "Total pizzas waiting for the oven: " +
                    orderedEventQueue.getNumberOfEventsWithPriority( 2 ) );
            System.out.println( "Total pizzas in oven: " + pizzasInOven );
            System.out.println( "Total pizzas delivered: " + pizzasDelivered );
            System.out.
                println( "Total queue time of events currently in queue: " + 
                    orderedEventQueue.getTotalQueueTime() );
        }
 
} // end method reportStatus()
 
    // a main method to simply start the application
    public static void main( String[] args )
    {
        new PizzaParlorSimulation();
 
    } // end main() method
 
} // end class PizzaParlorSimulation