3

I have a multithreaded Java program. The main thread executes the following code in a second thread, after which the second thread ends.

try{
   System.out.println(1); //prints
   doSomething();
   System.out.println(2); //doesn't print
} catch(Throwable t) {
   System.out.println(3); //doesn't print
}

I run this code and, on the rare occasion, I see 1 go to console, and 2 or 3 are absent. So it seems that doSomething is throwing some kind of error to cause the thread to stop. This happens about 0.5% of the time. Since it's not a Throwable that's causing the thread to terminate, what could possibly be going on?

The main thread keeps happily continuing after the second thread has stopped.

This is the code I'm using the create and run the second thread.

Runnable secondThread = new Runnable() { ... }
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
threadPoolExecutor.execute(secondThread);

EDIT: doSomething is a call to a REST API of an external website.

JacksonCounty
  • 115
  • 2
  • 8
  • Are you terminating the Jvm before the second thread has an opportunity to run? – PiRocks Jan 15 '20 at 16:47
  • Please show us the code you are using to wait on the second thread. – PiRocks Jan 15 '20 at 16:48
  • @PiRocks Well the main thread keeps running for many minutes after the second thread has finished. I see many log messages from the main thread after the `1` has been logged. `doSomething` only takes about 1 second. – JacksonCounty Jan 15 '20 at 16:48
  • 1
    Presumably `doSomething` is blocking or otherwise taking abnormally long to complete. It is not possible to avoid printing either 2 or 3, if this method either completes normally or throws. – Michael Jan 15 '20 at 16:49
  • @PiRocks I'm not waiting, I run them in parallel – JacksonCounty Jan 15 '20 at 16:49
  • @Michael There's no other error type? Like AssertionError for example or some other way to abruptly terminate the thread? – JacksonCounty Jan 15 '20 at 16:49
  • Throwable is the broadest thing you can possibly catch. There is nothing which can be caught that is not Throwable – Michael Jan 15 '20 at 16:51
  • @Michael Ok, but is there something that isn't Throwable that can't be caught that can necessarily bring down a thread (but not terminate the main thread)? – JacksonCounty Jan 15 '20 at 17:06
  • 1
    No there isn't. – Michael Jan 15 '20 at 17:07
  • Throwable should catch everything. If you don't wait on thread2 and main exits the entire Jvm will shutdown at which point you can't see any output from 2. Could you post the code you are using for creating thread2, as well as your main. – PiRocks Jan 15 '20 at 17:42
  • If you are concerned about some sort of exception escaping your catch you can use finally. – PiRocks Jan 15 '20 at 17:43
  • @PiRocks I've added the code – JacksonCounty Jan 15 '20 at 18:01
  • @Michael @PiRocks `doSomething` is a call to a `REST` API of an external website. – JacksonCounty Jan 15 '20 at 18:02
  • Do you know for sure that this api call terminates? – PiRocks Jan 15 '20 at 18:41
  • I am unable to reproduce, openjdk 8,11 and 12, Linux . I suspect that adding a ThreadPoolExecutor#shutdown call after you execute will fix your problem though. If it does I'll write up an answer explaining why. If not then I'm out of ideas unless I can find a way to reproduce. – PiRocks Jan 15 '20 at 18:48
  • @PiRocks I don't know for sure that the api call terminates. Are REST calls known to hang indefinitely? I'm using the `okhttp3` library. – JacksonCounty Jan 15 '20 at 19:30
  • This may be relevant, but likely not: https://stackoverflow.com/questions/53216831/okhttp-newcall-hangs-when-calling-restapi – PiRocks Jan 15 '20 at 19:58
  • You can use threadPoolExecutor.invokeAll for setting a timeout – PiRocks Jan 15 '20 at 20:01

2 Answers2

2

Sounds like doSomething does not terminate. Since you call an external service it probably hangs. Do the following: call jps It is in the same directory where java is located. It gives you a list of all java processes. Then call jstack process id

Thomas Krieger
  • 1,607
  • 11
  • 12
-1

The only answer to your question is that another thread is printing to System.out in between your first printout and your second.

To fix this, you should use a lock.

static Object lock = ...; //everyone who's printing to System.out should synchronize on this before printing to System.out

synchronized (lock) {
  try{
     System.out.println(1); //prints
     doSomething();
     System.out.println(2); //doesn't print
  } catch(Throwable t) {
     System.out.println(3); //doesn't print
  }
}
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • 1
    Don't know how you came to that conclusion. In this case, 2 or 3 **would** print eventually, just perhaps in a different sequence than expected. He's saying they're not printed at all. – Michael Jan 15 '20 at 16:54
  • @ControlAltDel The issue isn't that the other thread is printing inside `1` and `2`, it's that `2` and `3` never print which is a distinct thing. – JacksonCounty Jan 15 '20 at 17:40