This program reads in integers until a sentinel number is read. And prints the largest integer read
break;
            }
            else {



You don't need an else with a break.  The break ends execution inside the loop.  You can never reach the code after it in the loop unless it doesn't trigger.  Without all the else clauses, you can significantly reduce the amount of indentation.  

Your code could also return instead of break.  That would be clearer in my opinion.  

What's x?  What's y?  Why loop forever if you're just going to break out of it?  

In my opinion, your comments would be better replaced with more readable, self-commenting code.  

Consider the following 

    public static int readLargest(final int SENTINEL) {
        int largest = readInt(" ? ");
        for (int current = largest; current != SENTINEL; current = readInt(" ? ") ) {
            if (current &gt; largest) {
                largest = current;
            }
        }

        return largest;
    }


Which you'd use as 

    public void run() {
        int largest = readLargest(SENTINEL_NUMBER);

        if (largest == SENTINEL_NUMBER) {
            println("No numbers?");
        } else {
            println("Largest number is " + largest + ".");
        }
    }


By using a separate method, we consolidate the possibilities.  We only have two println statements.  In the original code, you had the latter option three times.  Here we only need one.  

This also makes the readLargest more reusable.  Even better might be to read all the values first, then call a findLargest method on that.  Then your readNumbers and findLargest methods would both be reusable separately.  Of course, you may not have gotten to Collection types yet.  

In your original code, sometimes y was the largest and sometimes x.  In this code, largest is always the largest unless the most recent read returns a larger value.  

I prefer the names current and largest as being more descriptive than single letter names.  I find that more important with largest.  I could live with x instead of current.  

I'm not sure that it's necessary to say SENTINEL_NUMBER.  The current variable is an integer.  What would SENTINEL be?  A cabbage?  Obviously not.  You'd only compare an integer to some kind of number.  Others may disagree.  In particular, you may want to look up Hungarian Notation.  

I prefer to pass the sentinel value as a parameter for flexibility.  

Since we don't use current outside of the loop, I think that the for loop has better scope than a while loop.  

The only comment that seems necessary is that readLargest will return the sentinel value if and only if there are no other numbers in the input (prior to the sentinel value).  Other than that, I feel that the code is pretty clear about what it is doing.  Perhaps some explanation of the initialization of largest.