1

I have the next code:

Executor exe = Executors.newFixedThreadPool(20);
while (true) {
   try {
       exe.execute(new DispatcherThread(serverSocket.accept()));
       continue;
   } catch (SocketException sExcp) {
       System.exit(-1);
   } catch (Exception excp) {
       System.exit(-1);
   }
}

For each DispatcherThread I create a connection to the database (it means I have 20 connections), what I need to know is how I can close the connection to the database when the thread is stopped or it stops or finishes its flow.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
zepol
  • 187
  • 5
  • 20
  • I would suggest closing the connection as part of the threads work and do some extra exception handling for the failure cases. – mschenk74 Jul 09 '14 at 19:16
  • Why can't the very last line of the run method of your runnable close the database connection that it opened? – selbie Jul 09 '14 at 19:16

2 Answers2

4

You cannot directly know when the thread is stopped, the closest thing you have is Thread#isAlive method but it may return false when the run method in the thread has finished but the thread may not be stopped since the JVM cannot guarantee it. But if your DispatcherThread class implements Runnable interface then you can write the clean up at the bottom of the run method.

Skeleton code:

class DispatcherThread implements Runnable {
    @Override
    public void run() {
        try {
            //open database connection an such...
            //...
            //handle the work here...
        } catch (...) {
            //ALWAYS handle the exceptions
        } finally {
            //cleanup tasks like close database connection
        }
    }
}

By the way, Thread suffix is not a good name for a class that technically is not a thread (because it doesn't extend from Thread). Instead, give a proper name according to what should do.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • I think that this answer is not correct. See my comments on the other answer for details. – Jashaszun Jul 09 '14 at 19:26
  • @Jashaszun I think it is. See my reply on the other answer for details. – Luiggi Mendoza Jul 09 '14 at 19:27
  • I think your answer is a little misleading. You actually can determine if a thread has stopped via `thread.isAlive()`. The problem here is that since `Exector.execute` takes a `Runnable` (not a `Thread`) the caller doesn't have access to the thread that the code inside the `Runnable` is actually executed on. Even if you did, that thread would most likely not go away once it was done executing your `Runnable`. It will most likely go back into a pool for future use (depends on implementation of course), so you really don't care when that thread finishes. – matt forsythe Jul 09 '14 at 21:59
  • It is misleading because 1.) you state that there is no way to tell when a thread finishes, when in fact there is, and 2.) although the OP is asking about how to know when the thread stops, you do not mention that knowledge of the thread stopping is irrelevant due to the way Executors work. – matt forsythe Jul 10 '14 at 03:58
  • @mattforsythe from [here](http://stackoverflow.com/a/17293394/1065197): *A Thread "dies" at the end of its `run()` method, or when `stop()` has been called.*, which is **true**. Calling `isAlive()` won't help you here neither calling `Thread#stop` since you don't have control of the thread when using `ExecutorService`. Also, it is a bad idea to close the resources outside the thread to begin with, so such answer is misleading. – Luiggi Mendoza Jul 10 '14 at 04:02
  • I was not advocating a different solution (and I am certainly not advocating calling `thread.stop()`). What I am advocating is more information. The OP's question (from the title) is "How to know when a thread stops or is stopped?" In your response: "You cannot directly know when the thread is stopped." That is false - you know when the thread is stopped because isAlive returns false. You also never dispel the OP's idea that the Exector thread stops when the runnable completes. – matt forsythe Jul 10 '14 at 04:18
  • @mattforsythe it is not false. If the thread has finished its `run` method, it doesn't mean it is stopped because the JVM cannot guarantee it. The closest thing you have is the `isAlive` method but it doesn't tell you if the thread was stopped or not. – Luiggi Mendoza Jul 10 '14 at 04:20
  • `isAlive` will indeed tell you when the thread has been stopped via `thread.stop()` unless the Executor is so poorly coded that it 1.) calls the deprecated stop method to begin with and then 2.) catches the ThreadDeath exception and fails to re-throw it (another no-no). I think it is sufficient to say that that is a rare enough boundary condition that it is insignificant. And `isAlive` captures the other scenario the OP is interested in, which is the completion of the runnable. You also haven't addressed my second point. All I am saying is your answer could be improved. – matt forsythe Jul 10 '14 at 04:34
  • @mattforsythe yes it will, but the fact that `isAlive` returns `false` means that the `run` method finished or the thread is stopped. And that's the gap: a thread can finish the execution of `run` method and still not being stopped at all because there's no guarantee that the thread is stopped. Using `isAlive` is not the right approach, and if you use it is similar (not the same) to post the code in the `finally` block of the `try-catch` statement as explained above. No need to keep arguing with you, the answer addresses OP's problem and main question. – Luiggi Mendoza Jul 10 '14 at 04:49
  • "No need to keep arguing with you" - I'm glad we can agree on that point... :) – matt forsythe Jul 10 '14 at 04:50
2

You could close the thread-specific connection at the end of your run() method.

A finally block would ensure that it happened however the run() method exited.

class DispatcherThread extends Runnable {
    public void run() {
       ...
       try {
          ...
       }
       finally {
            // Close the connection
       }
    }
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
  • But what if the thread is stopped, not by itself (via return or exception), but by another thread? Would the `finally` block still run? – Jashaszun Jul 09 '14 at 19:19
  • @Jashaszun [Does finally always execute in Java?](http://stackoverflow.com/q/65035/1065197) – Luiggi Mendoza Jul 09 '14 at 19:21
  • 1
    If you're using Thread.stop(), then no. That method is deprecated and inherently unsafe. Another thread could *signal* the thread to stop, at which point it could stop its work, and continue on to the finally block. – Andy Thomas Jul 09 '14 at 19:21
  • @LuiggiMendoza - That link contains the answer to Jashaszun's question, but it's hidden in a comment. – Andy Thomas Jul 09 '14 at 19:24
  • @AndyThomas Then this is not the correct answer, because it does not necessarily close the connection when it is done. – Jashaszun Jul 09 '14 at 19:24
  • @Jashaszun note that the signal sent to the thread is usually an `InterruptedException`. Besides, if using a `ExecutorService` then there's no way for the client to call `Thread#stop` *unless* you add such code in your `DispatcherThread` class, which seems pretty silly. – Luiggi Mendoza Jul 09 '14 at 19:26
  • @LuiggiMendoza Ok. Then both of these answers are correct. I'm sorry. – Jashaszun Jul 09 '14 at 19:27
  • So it means that if the Thread is stopped because an exception or something else, using the finally block would stop all of them? – zepol Jul 09 '14 at 19:32
  • @Jashaszun - If the thread exits because of an exception, the finally block will execute, and do what you asked. If you ask to close this thread's one connection, it will close just this thread's connection. – Andy Thomas Jul 09 '14 at 19:33
  • @Jashaszun - BTW, if you use a ThreadFactory as the second argument to your call to `newFixedThreadPool()`, you can name each thread, which is incredibly helpful during debugging. In some cases, may also want the thread factory to `setDaemon(true)` on new threads. – Andy Thomas Jul 09 '14 at 19:40
  • @user1623801 if an exception is thrown in one of the threads, the `finally` block will still be executed and the other threads will run apart *safely*. – Luiggi Mendoza Jul 09 '14 at 19:41
  • What about if the app is killed? Because is running in Linux as a StandAlone – zepol Jul 09 '14 at 19:54
  • If you `kill -9` it, the finally block will *not* execute. Neither will it execute if you take an axe to the machine. There isn't a perfect solution. A finally block at the end of the run() method is the best one I know of. There are ways for the other end of the connection to discover that the connection has been broken. – Andy Thomas Jul 09 '14 at 19:58