简体   繁体   中英

Why ScheduledExecutorService doesn't print stack trace?

Why we can't see the stacktrace in this example ?

public class NoStackTraceTester implements Runnable  {
    private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    private ScheduledFuture<?> lifeCheckFuture;

    @Override
    public void run() {
        lifeCheckFuture = startLifecheck();
    }

    private ScheduledFuture<?> startLifecheck()
    {
        Runnable lifeCheck = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("sending lifecheck ...");
                throw new RuntimeException("bang!");
            }
        };
        return scheduler.scheduleAtFixedRate(lifeCheck, 1000, 1000, TimeUnit.MILLISECONDS);
    }

    public static void main(String[] args) {
        new NoStackTraceTester().run();
    }
}

If you try to comment the exception you will the the repeative task of the lifecheck function. But if an exception is thrown, thread stop but with no detail :(

Do you have an idea why ?

An ExecutorService places any captured Throwable in the Future object. If you inspect this you can see what exception was thrown. This is not always desirable so you may have to catch and handle or log any exception in the run() method.

Note: once an exception escapes, the task is not repeated again.

Runnable lifeCheck = new Runnable() {
    @Override
    public void run() {
        try {
            System.out.println("sending lifecheck ...");
            throw new RuntimeException("bang!");
        } catch(Throwable t) {
            // handle or log Throwable
        }
    }
};

If you want an exception report, you must insert handling code yourself. The ExecutorService will not automatically send the exception trace to the standard output, and it is very good that it doesn't since this is rarely what we need in production code.

Basically, this is the approach:

public void run()
{
   try {
     System.out.println("sending lifecheck ...");
     throw new RuntimeException("bang!");
   } catch (Throwable t) { t.printStackTrace(); }
}

The afterExecute() method in ThreadPoolExecutor can be overridden:

class MyThreadPoolExecutor extends ThreadPoolExecutor {
    public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
            TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    public void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        // If submit() method is called instead of execute()
        if (t == null && r instanceof Future<?>) {
            try {
                Object result = ((Future<?>) r).get();
            } catch (CancellationException e) {
                t = e;
            } catch (ExecutionException e) {
                t = e.getCause();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            // Exception occurred
            System.err.println("Uncaught exception is detected! " + t
                    + " st: " + Arrays.toString(t.getStackTrace()));
        }
        // ... Perform cleanup actions
    }
}

final class MyTask implements Runnable {
    @Override public void run() {
        System.out.println("My task is started running...");
        // ...
        throw new ArithmeticException(); // uncatched exception
        // ...
    }
}

public class ThreadPoolExecutorHandler {
    public static void main(String[] args) {
        // Create a fixed thread pool executor
        ExecutorService threadPool = new MyThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());
        threadPool.execute(new MyTask());
        // ...
    }
}

source: https://medium.com/@aozturk/how-to-handle-uncaught-exceptions-in-java-abf819347906 (Please note, I modified the code posted here to not re-execute as the question only asks for stacktrace printing)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM