class Event {

        /** The event. */
        final WatchEvent<Path> event;

        /** The path. */
        final Path path;

        /**
         * Instantiates a new event.
         *
         * @param event
         *            the event
         * @param path
         *            the path
         */
        public Event(WatchEvent<Path> event, Path path) {
            super();
            this.event = event;
            this.path = path;
        }
    }

    /** The map of listeners.  This is managed by the watcher service*/
    private final Map<Path, List<WatchEventListener>> listeners;

    /** The working queue. The event queue is drained and all pending events are added in this list */
    private final ArrayList<Event> working = new ArrayList<>();

    /** The runnable. */
    private Thread runnable = null;

    /**
     * Instantiates a new event dispatcher.
     *
     * @param listeners
     *            the listeners
     */
    public EventDispatcher(Map<Path, List<WatchEventListener>> listeners) {
        super();
        this.listeners = listeners;
    }

    /** The event queue. */
    private final ArrayBlockingQueue<Event> eventQueue = new ArrayBlockingQueue<>(500);

    /*
     * (non-Javadoc)
     *
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {<FILL_FUNCTION_BODY>


        /*
         * The algorithm is naive:
         * a) work with not processed (in case);
         * b) drain the queue
         * c) work on newly collected
         * d) empty working queue
         */
        while (true) {
            // finish any pending ones
            for (Event e : working) {
                callListeners(e.event, e.path);
                if (Thread.interrupted()) {
                    return;
                }
                Thread.yield();
            }
            // drain the event queue
            eventQueue.drainTo(working);

            // work on new events.
            for (Event e : working) {
                callListeners(e.event, e.path);
                if (Thread.interrupted()) {
                    return;
                }
                Thread.yield();
            }

            // crear the working queue.
            working.clear();

            try {
                Thread.sleep(50);
            } catch (InterruptedException e1) {
                // TODO Auto-generated catch block
                return;
            }
        }
    
<no_super_class>