package org.ethereum.core;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * The class intended to serve as an 'Event Bus' where all EthereumJ events are
 * dispatched asynchronously from component to component or from components to
 * the user event handlers.
 *
 * This made for decoupling different components which are intended to work
 * asynchronously and to avoid complex synchronisation and deadlocks between them
 *
 * Created by Anton Nashatyrev on 29.12.2015.
 */
@Component
public class EventDispatchThread {
    private static final Logger logger = LoggerFactory.getLogger("blockchain");

    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    private static EventDispatchThread eventDispatchThread;

    /**
     * Returns the default instance for initialization of Autowired instances
     * to be used in tests
     */
    public static EventDispatchThread getDefault() {
        if (eventDispatchThread == null) {
            eventDispatchThread = new EventDispatchThread() {
                @Override
                public void invokeLater(Runnable r) {
                    r.run();
                }
            };
        }
        return eventDispatchThread;
    }

    public void invokeLater(final Runnable r) {
        if (executor.isShutdown()) return;
        executor.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    r.run();
                } catch (Exception e) {
                    logger.error("EDT task exception", e);
                }
            }
        });
    }


    public void shutdown() {
        executor.shutdownNow();
        try {
            executor.awaitTermination(10L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            logger.warn("shutdown: executor interrupted: {}", e.getMessage());
        }
    }
}

@@ -160,100 +160,9 @@
 ent.
-ExecutorService;%0Aimport java.util.concurrent.Executors;%0Aimport java.util.concurrent.TimeUnit
+*
 ;%0A%0A/
@@ -714,69 +714,355 @@
 nal 
-ExecutorService executor = Executors.newSingleThreadExecutor(
+BlockingQueue%3CRunnable%3E executorQueue = new LinkedBlockingQueue%3CRunnable%3E();%0A    private final ExecutorService executor = new ThreadPoolExecutor(1, 1,%0A            0L, TimeUnit.MILLISECONDS, executorQueue, new ThreadFactory() %7B%0A        @Override%0A        public Thread newThread(Runnable r) %7B%0A            return new Thread(r, %22EDT%22);%0A        %7D%0A    %7D
 );%0A%0A
@@ -1820,32 +1820,380 @@
             
-r.run();
+long s = System.nanoTime();%0A                    r.run();%0A                    long t = (System.nanoTime() - s) / 1_000_000;%0A                    if (t %3E 1000) %7B%0A                        logger.warn(%22EDT task executed in more than 1 sec: %22 + t + %22 ms, %22 + this +%0A                        %22. Executor queue size: %22 + executorQueue.size());%0A%0A                    %7D
 %0A           

Add warning output if a task on EDT is executed for more than 1 second