This question already has answers here:
How to start/stop/restart a thread in Java?
(9 answers)
Closed 7 years ago.
I have created a program which searches for files in a source folder. If it finds any file, it processes that file and moves it to a destination folder, then looks for a new file in the source folder. It has to keep on checking the source folder for a file.
I have used a thread to look for files in the source folder. The problem I am facing is whenever any exception is thrown during file processing, the thread gets stopped. I want the thread to be running even if an exception is thrown. It has to move the file that caused the error to some other folder and look for a new file in the source folder. How can I make the thread keep on running?
Eg:
public void run() {
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){
...
}
Update :
I should be more clear in my question. Actually there are 4 source folders and 4 destination folders. I have to perform the same operation in each source & destination pair. So i have created 4 threads in one class and do the operation in separate class.
class MainClass
{
public static void main(String[] args){
for(int i=0;i<4;i++){
SearchClass search = new SearchClass();
Thread thread = new Thread(search);
thread.start();
}
}
}
class SearchClass
{
public void run() {
try {
searchfile();
} catch(Exception e) {
e.printStackTrace();
}
}
public void searchfile(){ ... } }
All the thread wont stop running eventhough it caught any exception in middle. How can i do that?
If a thread is dying due to an uncaught exception, the answer is simple: catch the exception at an appropriate place so that you can keep going. Either catch the exception within your searchfile method, or make the run method call searchfile in a loop.
If you want your thread to keep running use a loop.
public void run() {
while(!Thread.interrupted())
try {
searchfile();
}
catch(Exception e) {
e.printStackTrace();
}
}
Inside your catch, you can move the file to the error folder then create a new object of the same thread and start it again.
unless i got you wrong, your code is missing the "keep running" nature, i.e. you need to have a loop somewhere:
public static void main(String[] args){
ExecutorService service = Executors.newFixedThreadPool(4);
// for each of your 4 folders
while (true) {
Future<File> searchResult = service.submit(new SearchTask());
try {
File foundFile = searchResult.get();
// handle found file
} catch (Exception e) {
// handle exception
}
}
}
private static class SearchTask implements Callable<File> {
#Override
public File call() {
return searchFile();
}
public File searchFile() {
// search & return found file
}
}
note that this is just a very simple extension of your example. it is still missing the parametrization of the SearchTask to actually be specific for a folder, handling of files & exceptions, etc. as mentioned in previous answers, your SearchTask should implement Runnable (i prefer Callable...), and IMHO it's always better to use an ExecutorService than to spawn threads manually. hope this helps...
I'm not entirely sure if this will work, yet here's a try.
public void run() {
try {
searchFile();
} catch(Exeption e) {
e.printStackTrace();
if(!Thread.currentThread().isAlive())
Thread.currentThread().start();
}
}
you said that the exception may be thrown during file process , so i put the processFile() in a try-catch block. but if it may be thrown during search, you may put it in a try-catch too.
public void run() {
while(!terminated) {
findNextFile();
try {
processFile();
} catch {
// handle error
}
}
}
Here are my assumptions based on your question and your clarification:
Each thread, in the run() method, only calls searchfile() once and not in a loop
your searchfile() method has a loop in it and you want that loop to continue running even if an exception is thrown in it.
you have some way of initializing each thread that you aren't showing us (and that isn't terribly important for this specific quiestion)
searchfile() does not declare that it throws any Exception
You aren't using a logging framework, but are instead using System.out (although using a logging framework is a Really Good Idea
Java 5 is OK (otherwise you'll have to use a different for() loop below
With these assumptions, you don't want to plan to catch an Exception in your run() method except for the purpose of logging that something went very wrong:
public void run() {
try {
searchfile();
} catch (RuntimeException e) {
System.out.println("Something went very wrong! Unexpected RuntimeException");
e.printStackTrace();
}
}
Note that the code catches RuntimeException. Always catch the most specific Exception that will do what you need. Then what you need is something such as the following in your searchfile() method:
File[] files = directory.listFiles();
for (File file : files) {
try {
// Do your normal file/directory processing here
} catch (Exception e) {
System.out.println("Exception processing file " + file.getName() + " " + e);
// Move "file" to another area
}
}
Since you are trapping unexpected Exceptions in the main loop of your Thread, your thread will continue processing after handling the Exception.
You can easily go with a workaround. Just run the needed logic for some amount of times and finish the job based on some criteria.
public class ThreadRestartWorkaround extends Thread {
public static void main(String[] args) {
ThreadRestartWorkaround th = new ThreadRestartWorkaround(5);
th.start();
}
private int maxCycles;
private int currentCycle;
public ThreadRestartWorkaround(int maxCycles) {
this.maxCycles = maxCycles;
}
#Override
public void run() {
while(executeSomeLogicUntilReachingTheLimit());
System.out.println("Finished due to exceeding the maxCycles config");
}
private boolean executeSomeLogicUntilReachingTheLimit() {
currentCycle++;
System.out.println("Executing logic for " + currentCycle + " time");
return currentCycle < maxCycles;
}
}
And the output is
Executing logic for 1 time
Executing logic for 2 time
Executing logic for 3 time
Executing logic for 4 time
Executing logic for 5 time
Finished due to exceeding the maxCycles config
Related
I have a callback which may throw a custom exception.
I'm trying to throw it, but it's not being catched on the outer scope, nor the compiler let me catch it, it says: "Exception is never thrown is the corresponding try block", even though it is.
this is my code:
public void openAsync(MessageAsyncCallback callback) {
try {
this.sendChannelOpen(this.getChannel(), getChannelOpenData().getFlags(), new MessageAsyncCallback() {
#Override
public void onComplete() throws NanoException {
// INanoPacket message = transport.getMessageByClassName(AudioServerHandshake.class.getName());
INanoPacket message = transport.getMessageByClassName(AudioClientHandshake.class.getName());
Log.info("Got audio server handshake, trying to client-handshake it");
sendClientHandshakeAsync((AudioServerHandshake) message, callback);
}
});
} catch (NanoException e) {
System.exit(-2);
}
}
and it doesn't let me catch NanoException
EDIT:
inside transport.getMessageByClassName I throw a NanoException.
EDIT2:
this is the method who invokes the exception:
public INanoPacket getMessageByClassName(String destClassName) throws NanoException {//} throws NanoException {
long startTime = System.currentTimeMillis(); // fetch starting time
INanoPacket message = this.getMessageFromTCPQueue();
while (!(message.getClass().getName().equals(destClassName)) && isRuntimeValid(startTime)) {
this.insertToTCPQueue(message); // put message back in queue
message = this.getMessageFromTCPQueue();
}
if (!(message.getClass().getName().equals(destClassName))) {
// timeout...
throw new NanoException("Couldn't find destination message: " + destClassName);
}
return message;
}
and I want to handle the exception not even in openAsync but on the method that calls openAsync.
why? because I'm handling messages coming from a remote device, this is why it's async. and I'm using some kind of timeout to wait for a specific message, and if the message isn't coming I want to restart the whole program.
Please notice that in your code you are not invoking onComplete method, you are defining it.
The exception would be thrown in a separate part of the code, possibly separate Thread (as it seems to be async). Therefore the "Exception is never thrown is the corresponding try block" message is right, as the exception will never be thrown when invoking this.sendChannelOpen(...) method.
Your try-catch statement needs to wrap the place where you invoke the onComplete method. As only by invoking onComplete method can you expect NanoException.
EDIT based on comments:
If you need to handle the exception throw in getMessageByClassName you can do it in onComplete method and not rethrow it. If you want to handle it somewhere else, you'd need to provide us the code of sendChannelOpen method or a place where the callback is invoked.
EDIT2 (based on question edits):
Please see the code below, as an example of how you can communicate between threads. I've used Latch, but there are other classes in java.util.concurrent that you may find useful.
BTW, I'm not going into the discussion why you want to restart the whole app on your NanoException, although there might be other options worth considering for recovering from that Exception.
import java.util.concurrent.CountDownLatch;
class NanoException extends Exception {}
interface MessageAsyncCallback {
void onComplete() throws NanoException;
}
public class AsyncApp {
private static final CountDownLatch errorLatch = new CountDownLatch(1);
public static void main(String[] args) {
new AsyncApp().run();
}
void run() {
sendChannelOpen("something", new MessageAsyncCallback() {
#Override
public void onComplete() throws NanoException {
// the whole try-catch-sleep is not really needed, just to wait a bit before exception is thrown
try {
// not needed, just to wait a bit before exception is thrown
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new NanoException();
}
throw new NanoException();
}
});
try {
System.out.println("This is a main thread and we wait here, while the other thread executes...");
errorLatch.await();
System.out.println("Latch has reached 0, will now exit.");
System.exit(-2);
} catch (InterruptedException e) {
System.out.println("Error in main thread.");
System.exit(-1);
}
}
void sendChannelOpen(String notImportant, MessageAsyncCallback troublesomeCallback) {
runSomethingInSeparateThread(troublesomeCallback);
}
void runSomethingInSeparateThread(MessageAsyncCallback troublesomeCallback) {
new Thread(() -> {
try {
troublesomeCallback.onComplete();
} catch (NanoException e) {
System.out.println("You can catch it here, and do system exit here or synchronize with main Thread as below");
errorLatch.countDown();
}
}).start();
}
}
This question already has answers here:
How to properly stop the Thread in Java?
(9 answers)
How to timeout a thread
(17 answers)
Closed 2 years ago.
so I am making a java code testing web application and I am running each code execution in a seperate thread. The problem is that sometimes tests have a time limit or the student just writes an infinite while loop. I've tried to terminate my testing thread with "best practices" such as using interrupts but I have no control over the inner workings of my compilation function so I can't just tell the thread to look if it has been interrupted or not. I'd like advice on how to handle this situation better.
Here is my bare bones example of what I want to achieve:
public class Main {
public static void main(String[] args) {
CodeExecutionThread cex = new CodeExecutionThread();
cex.start();
try {
cex.join(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread should stop at this point.");
}
}
class CodeExecutionThread extends Thread {
public CodeExecutionThread() {
}
#Override
public void run() {
infinite_operation();
}
public void infinite_operation() {
while(true) {
System.out.println("thread active");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I came accross the same problem more than once.
Probably not what you are looking for, but there is probably no better way than to use a flag inside the worker thread -- as described here for example: https://www.baeldung.com/java-thread-stop
When using a flag, there is of course a contract between the main thread and the worker -- you need to divide the infinite_operation into smaller chunks and check for the flag.
If you do not want that kind of contract or if it is not possible, consider using a process, which can be "safely" killed by OS (https://www.baeldung.com/java-process-api).
I have the following method and I am struggling to get 100% code coverage.
public final class SleepingHelper {
public static void sleepInMillis(Duration timeOfNextTry) {
try {
Thread.sleep(timeOfNextTry.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The question is how can I force Thread.sleep to throw an exception?
Edit: since it was marked as duplicate, I am still wondering what I would assert in the test ? The other question Is more generic.
You need to interrupt it from another thread. For example:
Thread t = new Thread() {
public void run () {
SleeperMillis.sleepInMillis(new Duration(10000000l));
}
}.start();
Thread.sleep(100); // let the other thread start
t.interrupt;
You don't need to actually interrupt the thread. You can use PowerMockito to mock the static method Thread.sleep()
#RunWith(PowerMockRunner.class)
#PrepareForTest(Thread.class)
public class TestClass {
#Test
public void testSleepInMillis() throws Exception {
PowerMockito.mockStatic(Thread.class);
PowerMockito.doThrow(new InterruptedException ()).when(Thread.class);
try {
SleepHelper.sleepInMillis(11);
fail("expected exception");
} catch (InterruptedException e) {
System.out.println("all good");
}
}
You don't test it, because you can't assert its results, and you can't assert it because Thread.sleep is not accurate or guaranteed to sleep for this duration of time, and the test results will differ from run to run.
Mocking is a better option here.
Btw, it is not just that your tests aren't predictable, your code that uses Thread.sleep in production is going to be unpredictable for the same reasons. Thread.sleep(some magic number goes here) usually indicates a badly written program.
I wouldn't bother testing it. 100% coverage is excessive. However, you could do it like this:
#Test
public void testException() throws Exception {
// Capture the system error stream, so that we can test that the expected exception is printed.
ByteArrayOutputStream capturedErrors = new ByteArrayOutputStream();
System.setErr(new PrintStream(capturedErrors));
// Create a new thread on which to run the candidate method.
Thread thread = new Thread() {
#Override
public void run() {
SleepingHelper.sleepInMillis(Duration.ofMillis(10));
}
};
// Start the second thread.
thread.start();
// Interrupt the second thread. (The candidate method hasn't finished yet. It takes 10 milliseconds to run.)
thread.interrupt();
// Wait for the thread to die (and write out the stack-trace).
thread.join();
// Test that the expected exception's stack trace was printed to the system error stream.
// The output should start with the exception's name.
String output = capturedErrors.toString();
int lengthOfExceptionName = "java.lang.InterruptedException".length();
assertEquals(output.substring(0, lengthOfExceptionName), "java.lang.InterruptedException");
}
for schedule executor:
executor = Executors.newSingleThreadScheduledExecutor();
Runnable ppt = new Runnable() {
public void run() {
try {
processTask();
} catch(Exception e) {
System.out.println(e.getMessage());
//need to be aware of this exception, no message is outputted
}
}
};
executor.scheduleWithFixedDelay(ppt, 0, 1000/20, TimeUnit.MILLISECONDS);
for processTask method:
private void processTask() {
try {
//task business logic
} catch(SomeOtherException e) {
System.out.println(e.getMessage());
//I want to be aware of this exception also
}
}
I know the task failed for a reason and I don't want it to continue after that point (I use executor.shutdown() to cancel it).
I just need to know what the error was when the exception is caught. It doesn't seem to do it in the above method.
Thanks in advance for any response.
You are putting try catch block in process task also that's why any problem in that method will resolve there and if you call shutdown then control would not return to the above method.
Runnable ppt = new Runnable() {
public void run() {
try {
processTask();
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
};
executor.scheduleWithFixedDelay(ppt, 0, 1000/20, TimeUnit.MILLISECONDS);
In this example you will get '/ by zero exception' and then scheduler will shutdown.
private static void processTask() {
try {
//task business logic
int x=2/0;
} catch(Exception e) {
System.out.println(e.getMessage());
//I want to be aware of this exception also
executor.shutdown();
}
}
Try to use e.printStackTrace(). getMessage() is a method of Throwable class (super class of all exceptions of Java) inherited by every exception class like ArithmeticException. The getMessage() method prints only the message part(If any message is available) of the output printed by object e. While printStackTrace() method prints full stack trace along with the line number where exception occurred with error message- See more at: http://way2java.com/exceptions/getmessage-printstacktrace/#sthash.QMvLohu3.dpuf
As answered by Kostja here
The message and the stacktrace are two distinct pieces of
information. While the stackstrace is mandatory, the message isnt.
Most exceptions deliver a message, and it is the best practice, but
some just don't and there's nothing to be done to fix it.
For more information you can see similar queries here link-1 and link-2.
How do we implement efficient exception handling when using threads.
I have a main program which creates 3 threads. How do we handle the exceptions for the exceptions thrown during the execution of thread?
Can we use the try/catch block or uncaughtexception. If so, can you please share some samples.
public class MyThreadTest {
public static void main(String[] args) {
Thread newThread = new Thread(new ThreadWithException());
// Add the handler to the thread object
newThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("ERROR! An exception occurred in " + t.getName() + ". Cause: " + e.getMessage());
}
});
newThread.start();
}
}
/**
* This thread throws a custom exception in its run method.
*/
class ThreadWithException implements Runnable {
#Override
public void run() {
throw new RuntimeException("Application Specific Exception!!");
}
}
Either you can use:
Thread#setUncaughtExceptionHandler to specify some code that is run when an exception is thrown (outside of normal program flow), or:
ExecutorService#invokeAll to run all of your blocks, and inspect the returned list for Future#get()'s throwing of ExecutionException. Another option is CompletionService, but this is slightly harder to use for such a simple case.
You can use try / catch block strategy:
Thread t = new Thread() {
#Override
public void run() {
try {
//..thread code
} catch (Exception e) {
}
}
};
It is easy to implement but in case of exception main thread of your application will never know what happened inside of child thread.
Better method would be to spawn threads using ExecutorService (as mentioned by FauxFaux). This will allow you to easily pass information about the error to main thread. Besides that, using ExecutorService allows you to write less code. You won't have to manage threads in your code but leave it for ExecutorService instead.
beacuse , recently, I have write a program with about 3 threads in order to fill a lot data from mysql and mongoDb to ElasticSearch. I share u my code.
I use java.util.concurrent.Executors.
First I have a main class. It calls
public void start() throws Exception {
this.logger.info("Main: Start the worker manually");
schedulerThreadPool = Executors.newScheduledThreadPool(this.maxNumberOfThread);
for (int i = 0; i < this.maxNumberOfThread; i++) {
Worker worker = new Worker();
long delay = i * this.sleepBetweenTaskStart;
schedulerThreadPool.scheduleAtFixedRate(worker, delay, this.minTimeBetweenEachTask, TimeUnit.MILLISECONDS);
}
}
And Worker implements Runnable and get Thread Id by below code.
this.threadId = Thread.currentThread().getId();
And just try catch in each Worker. Everything works normally.
#Override
public void run() {
try {
do...
} catch (Exception e) {
e.printStackTrace();
}
}