code: public void endOfData() {
  		ArrayList<Runnable> list = null;
  		synchronized (this) {
  			end = true;
  			if (waitingData.isEmpty()) {
  				list = listeners;
  				listeners = null;
  			}
  		}
  		if (list != null) {
  			for (Runnable listener : list) listener.run();
  		}
  		// notify after listeners
  		synchronized (this) {
  			this.notifyAll();
  		}
  	}
docs: Signal that no more data will be queued, so any waiting thread can be unblocked.