Xbai-hang
Xbai-hang

Reputation: 1

How can I shut down a Thread Pool correctly by use a while loop

Here is some main code of my question,I'm a Student in China,My English is not good, please the excuse me.

public static void main(String[] args) {
    ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Thread-%d").build();
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            5, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<>(),
            threadFactory, new ThreadPoolExecutor.DiscardPolicy()
    );
    // I submit 10 short task here
    // 👇I want when ThreadPool finish 10 task, then shut down the pool👇
    while (!poolExecutor.isTerminated() && poolExecutor.getCompletedTaskCount() == 10) {
        poolExecutor.shutdown();
    }
}

I want when ThreadPool finish 10th task, then shut down the pool,but the while loop does not seems to execute,the main Thread has been finished,but the core Thread of ThreadPool is still Waiting for task。

If I do not use the while loop and directly use poolExecutor.shutdown();. I can get the expected results. All the threads are finished and shutdown correctly. But I want to know what's the error of my code.

Upvotes: 0

Views: 259

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 339472

tl;dr

Call close in Java 19+.

shutdownAndAwaitTermination boilerplate

In Java 5+, you can use the boilerplate code named shutdownAndAwaitTermination given in the Javadoc for ExecutorService.

 void shutdownAndAwaitTermination(ExecutorService pool) {
   pool.shutdown(); // Disable new tasks from being submitted
   try {
     // Wait a while for existing tasks to terminate
     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
       pool.shutdownNow(); // Cancel currently executing tasks
       // Wait a while for tasks to respond to being cancelled
       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
           System.err.println("Pool did not terminate");
     }
   } catch (InterruptedException ex) {
     // (Re-)Cancel if current thread also interrupted
     pool.shutdownNow();
     // Preserve interrupt status
     Thread.currentThread().interrupt();
   }
 }

ExecutorService#close

Or, in Java 19+, call close.

See the source code at OpenJDK.

@Override
default void close() {
    boolean terminated = isTerminated();
    if (!terminated) {
        shutdown();
        boolean interrupted = false;
        while (!terminated) {
            try {
                terminated = awaitTermination(1L, TimeUnit.DAYS);
            } catch (InterruptedException e) {
                if (!interrupted) {
                    shutdownNow();
                    interrupted = true;
                }
            }
        }
        if (interrupted) {
            Thread.currentThread().interrupt();
        }
    }
}

Tip: Unless you have a special need, use Executors utility class to instantiate an ExecutorService.

Upvotes: 2

Xbai-hang
Xbai-hang

Reputation: 1

I have solved my question, It just a logic error, Sorry waste everyone's time, the correct code is that:

public static void main(String[] args) {
    ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Thread-%d").build();
    ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
            5, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<>(),
            threadFactory, new ThreadPoolExecutor.DiscardPolicy()
    );
    while (!poolExecutor.isTerminated()) {
        if (poolExecutor.getCompletedTaskCount() == 10) {
            poolExecutor.shutdown();
        }
        
    }
}

If I use the logical expression !poolExecutor.isTerminated() && poolExecutor.getCompletedTaskCount() == SORT_ALGORITHM_SIZE in while loop, It will probably beacause true && false and exit the loop. Then I can't close the thread pool

Thank you again for your help.

Upvotes: 0

user13290159
user13290159

Reputation:

There might be some issues with the getCompletedTaskCount method, but I'm not sure. I do know, that the suggested method of shutting down (and waiting for the imminent termination of) a ThreadPool is the following:

ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Thread-%d").build();
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
    5, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<>(),
    threadFactory, new ThreadPoolExecutor.DiscardPolicy()
);

// submit to poolExecutor

poolExecutor.shutdown();
// This is where the magic happens:
// maxTimeToWait is the amount of unitOfTimes to wait at max, before just continuing.
// javadoc: Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
poolExecutor.awaitTermination(maxTimeToWait, unitOfTime);

Upvotes: 0

Related Questions