I saw this in the java docs: ScheduledAtFixedRate, it says
If any execution of the task
encounters an exception, subsequent
executions are suppressed
I don't want this to happen in my application. Even if I see an exception I would always want the subsequent executions to occur and continue. How can I get this behavior from ScheduledExecutorService.
Surround the Callable.call method or the Runnable.run method with a try/catch...
eg:
public void run()
{
try
{
// ... code
}
catch(final IOException ex)
{
// handle it
}
catch(final RuntimeException ex)
{
// handle it
}
catch(final Exception ex)
{
// handle it
}
catch(final Error ex)
{
// handle it
}
catch(final Throwable ex)
{
// handle it
}
}
Note that catching anything other than what the compiler tells you too (the IOException in my sample) isn't a good idea, but there are some times, and this sounds like one of them, that it can work out if you handle it properly.
Remember that things like Error are very bad - the VM ran out of memory etc... so be careful how you handle them (which is why I separated them out into their own handlers rather than just doing catch(final Throwable ex) and nothing else).
Try VerboseRunnable class from jcabi-log, which does the wrapping suggested by TofuBeer:
import com.jcabi.log.VerboseRunnable;
Runnable runnable = new VerboseRunnable(
Runnable() {
public void run() {
// do business logic, may Exception occurs
}
},
true // it means that all exceptions will be swallowed and logged
);
Now, when anybody calls runnable.run() no exceptions are thrown. Instead, they are swallowed and logged (to SLF4J).
I had the same problem. I also tried that try block within run() method but it doesn't work.
So I did something is working so far:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
public class Test2 {
static final ExecutorService pool = Executors.newFixedThreadPool(3);
static final R1 r1 = new R1();
static final R2 r2 = new R2();
static final BlockingQueue deadRunnablesQueue = new LinkedBlockingQueue<IdentifiableRunnable>();
static final Runnable supervisor = new Supervisor(pool, deadRunnablesQueue);
public static void main(String[] args) {
pool.submit(r1);
pool.submit(r2);
new Thread(supervisor).start();
}
static void reSubmit(IdentifiableRunnable r) {
System.out.println("given to an error, runnable [" + r.getId()
+ "] will be resubmited");
deadRunnablesQueue.add(r);
}
static interface IdentifiableRunnable extends Runnable {
String getId();
}
static class Supervisor implements Runnable {
private final ExecutorService pool;
private final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue;
Supervisor(final ExecutorService pool,
final BlockingQueue<IdentifiableRunnable> deadRunnablesQueue) {
this.pool = pool;
this.deadRunnablesQueue = deadRunnablesQueue;
}
#Override
public void run() {
while (true) {
IdentifiableRunnable r = null;
System.out.println("");
System.out
.println("Supervisor will wait for a new runnable in order to resubmit it...");
try {
System.out.println();
r = deadRunnablesQueue.take();
} catch (InterruptedException e) {
}
if (r != null) {
System.out.println("Supervisor got runnable [" + r.getId()
+ "] to resubmit ");
pool.submit(r);
}
}
}
}
static class R1 implements IdentifiableRunnable {
private final String id = "R1";
private long l;
#Override
public void run() {
while (true) {
System.out.println("R1 " + (l++));
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
System.err.println("R1 InterruptedException:");
}
}
}
public String getId() {
return id;
}
}
static class R2 implements IdentifiableRunnable {
private final String id = "R2";
private long l;
#Override
public void run() {
try {
while (true) {
System.out.println("R2 " + (l++));
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
System.err.println("R2 InterruptedException:");
}
if (l == 3) {
throw new RuntimeException(
"R2 error.. Should I continue to process ? ");
}
}
} catch (final Throwable t) {
t.printStackTrace();
Test2.reSubmit(this);
}
}
public String getId() {
return id;
}
}
}
You can try to comment out Test2.reSubmit(this) to see that without it, R2 will stop working.
If all you want is subsequent executions to occur and continue even after exceptions, this code should work.
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Runnable task = new Runnable() {
#Override
public void run() {
try{
System.out.println(new Date() + " printing");
if(true)
throw new RuntimeException();
} catch (Exception exc) {
System.out.println(" WARN...task will continiue"+
"running even after an Exception has araised");
}
}
};
executor.scheduleAtFixedRate(task, 0, 3, TimeUnit.SECONDS);
If a Throwable other than Exception has occurred you might not want subsequent executions get executed.
Here is the output
Fri Nov 23 12:09:38 JST 2012 printing _WARN...task will
continiuerunning even after an Exception has raisedFri Nov 23
12:09:41 JST 2012 printing _WARN...task will continiuerunning
even after an Exception has raisedFri Nov 23 12:09:44 JST 2012
printing _WARN...task will continiuerunning even after an
Exception has raisedFri Nov 23 12:09:47 JST 2012 printing
_WARN...task will continiuerunning even after an Exception has raised
Related
I'm trying to find a way to set a time limit for running a block of code (force-terminate it when time is up) without modifying the internals of the block of code. Here's what I tried to do: I first copied the TimeLimitedCodeBlock class from this link: Java-how-to-set-timeout
import java.util.*;
import java.util.concurrent.*;
public class TimeLimitedCodeBlock {
public static void runWithTimeout(final Runnable runnable, long timeout, TimeUnit timeUnit) throws Exception {
runWithTimeout(new Callable<Object>() {
#Override
public Object call() throws Exception {
runnable.run();
return null;
}
}, timeout, timeUnit);
}
public static <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<T> future = executor.submit(callable);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
return future.get(timeout, timeUnit);
}
catch (TimeoutException e) {
future.cancel(true);
throw e;
}
catch (ExecutionException e) {
Throwable t = e.getCause();
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof Exception) {
throw (Exception) t;
} else {
throw new IllegalStateException(t);
}
}
}
}
And here is what I ran using the class defined above:
public static void main(String [] args)
{
try{
TimeLimitedCodeBlock.runWithTimeout(new Runnable()
{
public void run()
{
try{
while(true){}
}catch(Exception e){}
}},1,TimeUnit.SECONDS);
}
catch(Exception e){}
}
And it's not terminating. How should I fix it so that it terminates?
Code snippet that I've used to do something similar:
LOG.info("Time limited task started on monitored thread, with limit (" + limit + ")");
final ZonedDateTime start = nowUTC();
final Thread thread = new Thread(toRun);
thread.setDaemon(true);
final List<Throwable> exceptions = new ArrayList<>();
thread.setUncaughtExceptionHandler((t, e) -> {
exceptions.add(e);
});
thread.start();
// Check and wait for completion.
while (thread.isAlive()) {
if (!isWithinLimit(start, nowUTC())) {
LOG.error("Interrupting thread, did not complete before limit (" + limit + ")");
try {
thread.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
throw new TimeLimitExceedException("Execution limit of " + limit
+ " exceeded. (Has been running since " + start + ")");
}
try {
Thread.sleep(POLLING_PERIOD.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// If it failed because of an exception, we want to trigger this.
if (!exceptions.isEmpty()) {
final Throwable exception = exceptions.get(0);
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception;
} else {
throw new RuntimeException(exception);
}
}
final Duration runTime = Duration.between(start, nowUTC());
LOG.info("Time limited task has completed in (" + runTime + ") vs limit of (" + limit
+ ").");
TLDR:
I just start whatever I'm running as a new thread that is set as a daemon (just in case it is the last thing running), then I get a reference to that and poll it, and call thread.interrupt() if it goes over the time limit.
Other context & bells and whistles
This is part of a class that has some other state, like duration and what it is running
Also track some exceptions so that it can be spit out at the end if necessary
In my quest to learn Java better, I have been trying to understand exception handling. I cannot understand why the following code fails to compile.
The compiler message is:
TestExceptionHandling.java:12: error: exception StupidException is never thrown in body of corresponding try statement
catch (StupidException stupidEx) {
^
In the try block, method exTest.doExTest() is called. In this method I catch an InterruptedException and in its catch block I throw a new StupidException.
So why does the compiler say it's not thrown? What am I missing? Can any expert help me see my mistake please?
public class TestExceptionHandling {
public static void main(String argv[]) {
String output = "";
try {
output = "\nCalling method doExTest:\n";
exTest.doExTest();
}
catch (StupidException stupidEx) {
System.out.println("\nJust caught a StupidException:\n " + stupidEx.toString());
}
System.out.println(output);
}
}
class exTest {
static long mainThreadId;
protected static void doExTest() { //throws StupidException
mainThreadId = Thread.currentThread().getId();
Thread t = new Thread(){
public void run(){
System.out.println("Now in run method, going to waste time counting etc. then interrupt main thread.");
// Keep the cpu busy for a while, so other thread gets going...
for (int i = 0; i < Integer.MAX_VALUE; i++) {
int iBoxed = (int)new Integer(String.valueOf(i));
String s = new String("This is a string" + String.valueOf(iBoxed));
}
// find thread to interrupt...
Thread[] threads = new Thread[0];
Thread.enumerate(threads);
for (Thread h: threads) {
if (h.getId() == mainThreadId) {
h.interrupt();
}
}
}
};
t.start();
try {
Thread.sleep(5000);
}
catch (InterruptedException e){
System.out.println("\nAn InterruptedException " + e.toString() + " has occurred. Exiting...");
throw new StupidException("Got an InterruptedException ", e); // ("Got an InterruptedException. Mutated to StupidException and throwing from doExTest to caller...", e);
}
}
}
class StupidException extends Exception {
public StupidException(String message, Throwable t) {
super(message + " " + t.toString());
}
public String toString() {
return "Stupid Exception: " + super.toString();
}
}
Methods need to explicitly declare that they throw exceptions (with the exception of runtime exceptions, which are a bit different). Try declaring your doExTest method as
protected static void doExTest() throws StupidException {
...
}
I am trying to signal between two threads using the below FutureResult class which extends FutureTask class. When run the script, it prints the following result.
SENDING: 0
SENT: 0
POLL: FutureResult#513431
SIGNALLED: FutureResult#513431
Then the program hang up forever. I expect FutureResult instance should return the value from it's blocking get method. Then print the result in the console. But FutureResult.get is blocking forever.
import java.util.concurrent.*;
/**
* Created by someone on 20/08/2015.
*/
final public class FutureResult<T> extends FutureTask<T> {
private static final Object SS = "SS";
public FutureResult() {
super(() -> null);
}
public void signal(final T value) {
set(value);
}
public void signalError(final Throwable throwable) {
setException(throwable);
}
public static void main(String... args) throws Exception {
final ArrayBlockingQueue<FutureResult> queue = new ArrayBlockingQueue<>(1000000);
new Thread(() -> {
while (true) {
try {
final FutureResult poll = queue.take();
System.out.println("POLL: " + poll);
if (poll != null) {
poll.signal(SS);
System.out.println("SIGNALLED: " + poll);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 1; i++) {
final FutureResult<Object> result = new FutureResult<>();
System.out.println("SENDING: " + i);
queue.offer(new FutureResult());
try {
System.out.println("SENT: " + i);
result.get();
System.out.println("GOT : " + i);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}).start();
}
}
This is the problem:
queue.offer(new FutureResult());
You're setting the value on one FutureResult, but that's not the one you're waiting for. Just change that line to:
queue.offer(result);
and it works fine.
Looks like the confusion is in the use of FutureTask. FutureTask is designed as a Runnable; running it is necessary.
Honestly, based on the code, it looks like the custom code is implementing something similar to FutureTask. If the intent here is to learn to use FutureTask, then create a FutureTask instance with a "run" method, and then execute that run method. On completion of the run method, the FutureTask.get() will complete.
My apologies for throwing this random subject, but I did not come up with a better name,
class ReportSenderRunnable implements Runnable {
private final LPLogCompressor compressor;
public ReportSenderRunnable(final LPLogCompressor compressor) {
this.compressor = compressor;
}
#Override
public void run() {
executeTasks();
}
private void executeTasks() {
try {
// compressor.compress();
reportStatus = ReportStatus.COMPRESSING;
System.out.println("compressing for 10 seconds");
Thread.sleep(10000);
} catch (final IllegalStateException e) {
logCompressionError(e.getMessage());
} /*catch (final IOException e) {
logCompressionError(e.getMessage());
}*/ catch (InterruptedException e) {
logCompressionError(e.getMessage());
}
try {
reportStatus = ReportStatus.SENDING;
System.out.println("sending for 10 seconds");
Thread.sleep(10000);
} catch (final InterruptedException e) {
reportStatus = ReportStatus.EXCEPTION_IN_SENDING;
}
try {
reportStatus = ReportStatus.SUBMITTING_REPORT;
System.out.println("submitting report for 10 seconds");
Thread.sleep(10000);
} catch (final InterruptedException e) {
reportStatus = ReportStatus.EXCEPTION_IN_SUBMITTING_REPORT;
}
System.out.println("Report Sender completed");
reportStatus = ReportStatus.DONE;
}
private void logCompressionError(final String cause) {
logError(ReportStatus.COMPRESSING, cause);
reportStatus = ReportStatus.EXCEPTION_IN_COMPRESSION;
}
private void logError(final ReportStatus status, final String cause) {
LOGGER.error("{} - {}", status, cause);
}
}
Ideally, statements like
System.out.println("sending for 10 seconds");
Thread.sleep(10000);
will be replaced by actual tasks, but for now assuming this is the case, and they way it runs is
private void submitJob() {
final ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
final LPLogCompressor lpLogCompressor = getLpLogCompressor();
executorService.execute(getReportSenderRunnable(lpLogCompressor));
} catch (final IOException e) {
reportStatus = ReportStatus.EXCEPTION_IN_COMPRESSION;
LOGGER.debug("Error in starting compression: {}", e.getMessage());
}
System.out.println("started Report Sender Job");
}
My question was how to effectively test this code? The one I wrote is
#Test
public void testJobAllStages() throws InterruptedException, IOException {
final ReportSender reportSender = spy(new ReportSender());
doReturn(compressor).when(reportSender).getLpLogCompressor();
when(compressor.compress()).thenReturn("nothing");
reportSender.sendAndReturnStatus();
Thread.sleep(10);
assertEquals(ReportStatus.COMPRESSING, reportSender.getCurrentStatus());
Thread.sleep(10000);
assertEquals(ReportStatus.SENDING, reportSender.getCurrentStatus());
Thread.sleep(10000);
assertEquals(ReportStatus.SUBMITTING_REPORT, reportSender.getCurrentStatus());
}
This runs well for above code.
To me this is crappy for following reasons
Not all tasks would take same time in ideal cases
Testing with Thread.sleep will take too much time and also adds non-determinism.
Question
How do I test this effectively?
You could add a class with a method (e.g., TimedAssertion.waitForCallable) that accepts a Callable, which then uses an ExecutorService to execute that Callable every second until it returns true. If it doesn't return true in a specific period of time, it fails.
You would then call that class from your test like this:
boolean result;
result = new TimedAssertion().waitForCallable(() ->
reportSender.getCurrentStatus() == ReportStatus.COMPRESSING);
assertTrue(result);
result = new TimedAssertion().waitForCallable(() ->
reportSender.getCurrentStatus() == ReportStatus.SENDING);
assertTrue(result);
...etc. This way, you can easily wait for a particular state in your code to be true, without waiting too long -- and you can reuse this new class anywhere that you need this sort of assertion.
Based on #Boris the Spider comment, I made use of mocks and here is what my tests look like
#Mock
private ReportSenderRunnable reportSenderRunnable;
#Mock
private LPLogCompressor compressor;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test(timeout = 1000)
public void testJobNoException() throws InterruptedException, IOException {
final ReportSender reportSender = spy(new ReportSender());
doReturn(compressor).when(reportSender).getLpLogCompressor();
when(compressor.compress()).thenReturn("nothing");
reportSender.sendAndReturnStatus();
Thread.sleep(10);
assertEquals("Job must be completed successfully", ReportStatus.DONE,
reportSender.getCurrentStatus());
}
#Test(timeout = 1000)
public void testJobWithIllegalStateException() throws Exception {
final ReportSender reportSender = spy(new ReportSender());
doReturn(compressor).when(reportSender).getLpLogCompressor();
doThrow(IllegalStateException.class).when(compressor).compress();
reportSender.sendAndReturnStatus();
Thread.sleep(10);
assertEquals("Job must failed during compression", ReportStatus.EXCEPTION_IN_COMPRESSION,
reportSender.getCurrentStatus());
}
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)