2016-07-16 4 views
2

Я реализую службу, которая выполняет некоторые более длительные запущенные задачи, которые эмулируются здесь Thread.sleep(10000). Когда я выполняю ctrl + c, я никогда не получаю InterruptedException, которого я ожидал бы. Мне интересно, почему.Безопасно ли закрывать ScheduledExecutorService?

package simple; 

import my.util.Now; 
import io.dropwizard.lifecycle.Managed; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class EmailSender implements Managed { 

    private static final Logger LOGGER = LoggerFactory.getLogger(EmailSender.class); 
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3); 

    // Constructor 
    public EmailSender() {} 

    @Override 
    public void start() { 
     LOGGER.info("Starting email sender thread: {}", Thread.currentThread().getName()); 
     Runnable task =() -> { 
      LOGGER.info("Running: {} in thread: {}", Now.now(), Thread.currentThread().getName()); 
      try { 
       Thread.sleep(10000); 
      } catch (InterruptedException ie) { 
       LOGGER.error("Task is being interrupted: {}", ie.getMessage()); 
      } 
     }; 
     executorService.scheduleAtFixedRate(task, 0, 5, TimeUnit.SECONDS); 
    } 

    @Override 
    public void stop() { 
     LOGGER.info("Stopping email sender thread: {}", Thread.currentThread().getName()); 
     executorService.shutdown(); 

    } 
} 

ли это с уверенностью предположить, что executorService.shutdown(); ждет, пока выполнение закончится для выполнения этой задачи таким образом?

+2

Документы по существу сказать, что все это: [ 'выключение()'] (https://docs.oracle.com/javase/7/ docs/api/java/util/concurrent/ExecutorService.html # shutdown()) просто мешает исполнителю принимать новые материалы. Вероятно, вы хотели ['shutdownNow()'] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()), который прерывает выполнение потоков. И нет, последнее не безопасно по тем же причинам, что прерывание потоков не очень безопасно. – dhke

ответ

2

shutdown не останавливает запущенные задачи, но даже выполняет ожидания в очереди.

Используйте shutdownNow, если вы хотите немедленно прекратить работу.

1

Можно ли предположить, что executorService.shutdown(); ждет, пока выполнение закончится для этой задачи?

Нет. Он не будет ждать завершения всех потоков.

Рекомендуемый способ от оракула документации странице 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 ie) { 
    // (Re-)Cancel if current thread also interrupted 
    pool.shutdownNow(); 
    // Preserve interrupt status 
    Thread.currentThread().interrupt(); 
    } 

shutdown(): Инициирует процедуру завершения работы, в котором выполняются ранее представленные задачи, но никакие новые задачи не будут приняты.

shutdownNow(): Пытается прекратить все активное выполнение задач, останавливает обработку ожидающих задач и возвращает список задач, ожидающих выполнения.

Вы можете изменить

if (!pool.awaitTermination(60, TimeUnit.SECONDS)) 

в

while (!pool.awaitTermination(60, TimeUnit.SECONDS)) 
Thread.sleep(60000); 
Смежные вопросы