Вопрос

So far in my experiments with the executorservice I've had a lot of advice that involves using future.get, and then future.cancel in order to throw a thread interrupt which then needs to be caught in the thread, and handled there. My question is a little different.

Assuming that I was running a thread that simply kept track of how long things were running and if they passed by some threshold, would this be a good way to kill the executorservice and all running threads?

Example thought process:

ExecutorService threadPool = Executors.newFixedThreadPool(12);
timekeeper.start();
List<Future<?>> taskList = new ArrayList<Future<?>>();
    for (int i = 0; i < objectArray.length; i++) {
        Future<?> task = threadPool.submit(new ThreadHandler(objectArray[i], i));
        taskList.add(task);
        Thread.sleep(500);
    }

if(timekeeper.now() > 60)
    threadpool.shutdownNow();
}

Would this work? I have no way to check since my threads fail extremely infrequently (about 1/700 runs, and only at certain hours of the day when I'm not working).

Это было полезно?

Решение

The shutdownNow method attempts to interrupt all of active task threads, and this would only work if the tasks were coded to respected interrupts. They would need to:

  • check to see if the interrupt flag has been set in long running loops, and

  • deal with InterruptedExceptions correctly.

Basically the tasks needs to cooperate for interrupts to work. If they don't cooperate, there is no safe and reliable way to stop them ... apart from exiting the JVM.


Above someone mentioned the .stop() method as a comment, can you provide commentary as to why this would be a bad idea?

The Thread.stop() method is deprecated because it is fundamentally unsafe. Stopping a thread can leave critical data structures in an intermediate state, and can interfere with other threads that were interacting with it in various ways. It is theoretically possible to use stop safely, but it is difficult to work out a set of general preconditions that are sufficient to ensure that nothing bad happens.

Другие советы

This is what I would do

ExecutorService threadPool = Executors.newFixedThreadPool(12);
List<Future<?>> taskList = new ArrayList<Future<?>>();
for (int i = 0; i < objectArray.length; i++) {
    taskList.add(threadPool.submit(new ThreadHandler(objectArray[i], i)));
threadPool.shutdown();
threadPool.awaitTermination(60, TimeUnit.SECONDS); // or what ever
threadPool.shutdownNow();

This assumes your tasks will honour interrupts. If they do not there is no clean way to kill a thread (except using a flag which is much the same thing)


Reasons not to use Thread.stop() here

  • You don't have access to the Thread objects to call stop() on.
  • If a task is ignores interrupt() it is likely to be poorly behaved, which can leave the heap in a corrupt state.
  • Calling stop() should stop the task but won't stop a thread pool thread unless it has been shutdown() as it traps it. (Admittedly, easy to work around)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top