Printing a stack on the console when replenishing items eliminates the exception

I just wrote a remarkably simple "Stack" class in Java on the eclipse Juno IDE, which has 2 operations - push and pop. One check I have in the pop () method is to see if it is empty; if so, I throw a NoSuchElementException. Therefore, if I click 1,2,3,4,5 sequentially, and then pop the elements five times, I expect to see 5,4,3,2,1 printed in that order. But after adding five elements, if I intentionally try to push the stack in SIX times, I would expect 5,4,3,2,1 and then a NoSuchElementException.

What happens in my case is that the console unexpectedly throws a NoSuchElementException (i.e. not always after printing 5,4,3,2,1, sometimes it prints:

stack pop: 5 stack pop: 4 Exception in thread "main" java.util.NoSuchElementException: Stack Underflow stack pop: 3 stack pop: 2 stack pop: 1 at Stack.pop(Stack.java:29) at Stack.main(Stack.java:47) 

and sometimes he prints:

 Exception in thread "main" stack pop: 5 stack pop: 4 stack pop: 3 stack pop: 2 stack pop: 1 java.util.NoSuchElementException: Stack Underflow at Stack.pop(Stack.java:29) at Stack.main(Stack.java:47) 

My goal is to understand what regulates this behavior. Since I use print statements (and not a log, which may have a similar implementation queue under it), I would expect the instructions to be fine, but I suspect there is something concurrency here. Below is my code:

import java.util.NoSuchElementException;

 public class Stack { private Node first; private int size; private class Node{ Node next; int value; } public Stack(){ size=0; first=null; } public void push(int x){ Node previousFirst = first; first = new Node(); first.value = x; first.next = previousFirst; size++; } public int pop(){ if(first == null){ throw new NoSuchElementException("Stack Underflow"); } int poppedNodeVal = first.value; first = first.next; size--; return poppedNodeVal; } public static void main(String[] args) { Stack stack1 = new Stack(); stack1.push(1); stack1.push(2); stack1.push(3); stack1.push(4); stack1.push(5); for(int i=5; i>=0;i--){ System.out.println("stack pop: " + stack1.pop()); } } } 

Any thoughts on how to reliably print this and, more importantly, what could cause this non-deterministic exception printing in the console?

+4
source share
3 answers

Your exception does not get caught, so it stops the execution of the program. Probably the problem is related to

a) You insert 5 elements and extract 6, change your loop to

  for(int i = 5; i >0; i--) 

b) An exception is thrown after System.out.println for all 5 elements (otherwise, these lines will not be printed at all, since the program exits). But part of the content has not yet been printed to the console (it has a buffer). When the exception is thrown, it is printed on System.err (another buffer), since in your case both ends of System.out and System.err end in the console, you get mixed content.

Wrap your for in a try/catch and catch the exception. Print a System.out message System.out this. You will see that it appears before printing the last item.

+2
source

this is because System.err and System.out are not the same thread, it can sometimes happen that they are not synchronized. System.err for exception, System.out is what you use.

maybe you want to try something like this:

 System.setErr(System.out); 

Thaw will direct the standard System.err to System.out, now you should have the correct 5,4,3,2,1 exception stream.

Obviously, if the two threads are separated, there is a reason, so you can do what I told you, but try to do this only during testing (for example, in jUnit)

+3
source

Your messages use System.out , but exceptions are printed on System.err . The Eclipse console does not synchronize these two streams so that they are not displayed in order on the console. Try sending your messages to System.err and they should be in order.

+2
source

Source: https://habr.com/ru/post/1498772/


All Articles