Vilius
Vilius

Reputation: 1189

Java strange thread termination

I have a system with multiple threads running - my main-thread just checks if there are jobs to be done and if there are some, it calls the sub-threads (notifyAll()) who will execute it. After that, the sub-threads just wait() until there are some new tasks.

Actually, the thread-system is running reliable, but after a longer runtime (3-5h), some sub-threads just die without a warning or an error. They just exit one after another - but again only with a time-range of 2-x hours. I have used jconsole to check this phenomenon, which threads are running and how they just simply disappear.

Furthermore, the main-thread is executing every second, but the sub-threads are mainly wait()ing and are not often used at all (since there are not so many tasks in the test environment).

The only reason I can think of is, that the JVM turns off the sub-threads since they are not often used enough?

I would be very thankfull for your help!

P.S. All threads are not defined as daemons and the main-thread just works fine!

edit

Thanks for your answers, but I actually use this loop.

public void addTask (Task in_task) throws InterruptedException {
        synchronized (tasks) {
              while (tasks.size() == MAXIMUM_NUMBER_OF_TASKS) {
                   tasks.wait();
              }
              tasks.offer(in_task);
              tasks.notifyAll();
        }
}

I use this loop, so that only some speciall amount of tasks will be executed.

Upvotes: 1

Views: 627

Answers (4)

rodion
rodion

Reputation: 15029

I recommend using one of the Executors for managing your tasks. There are less chances that you will lose a possible error or exception in one of you sub-threads, so it should help you debug you program. Any exception that happens in a sub-thread will be stored inside the Future object and rethrown as an ExecutionException when you call Future#get().

List<Future<Void>> taskResults = new ArrayList<Future<Void>>();
ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);

while(!finished){
  //say you wait (blocking) for a new task here
  Callable<Void> task = getNextTask();

  //put the task into the pool
  Future<Void> result = es.submit(task);
  taskResults.add(result);
}

//3 hours later, set `finished` to true

//at the end check that no exceptions were thrown
for(Future<Void> result : taskResults){
  try{
    result.get();
  }catch(ExecutionException e){
    //there was an error
    e.getCause().printStackTrace();
  }catch(InterruptedException e){
    //irrelevant
  }
}

In general, stuff in the java.util.concurrent helps you write much more robust multi-threaded applications, without having to resort to Object#wait() and other concurrency primitives (unless you are learning, of course).

Upvotes: 1

MarcB
MarcB

Reputation: 559

Try setting an uncaught exception handler on each thread. There is a setUncaughtExceptionHandler() function on the Thread. Implement the UncaughtExceptionHandler interface and print the exception.

General idea, but don't do it with anonymous classes/methods:

thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
  public void uncaughtException(Thread t, Throwable e)
  {
    e.printStackTrace();
  }
}); 

Upvotes: 0

jmg
jmg

Reputation: 7414

Instead of writing your own multi-threaded task execution solution you could use java.util.concurrent.ThreadPoolExecutor. This would probably be a good idea no matter whether you are able to fix this bug or not.

Upvotes: 2

JB Nizet
JB Nizet

Reputation: 691745

The documentation for Object.wait() says:

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

Maybe you didn't follow this advice and got a spurious wakeup or interrupt?

Upvotes: 5

Related Questions