2012-10-10 18 views
9

Mam wiele zadań wewnątrz TheadPoolExecutor. Mam przycisk zatrzymania na moim interfejsie, który powinien natychmiast zakończyć wszystkie wątki wewnątrz ThreadPoolExecutor. Szukam sposobu, aby to zrobić. (bez shutDown() lub shutDownNow()).Jak wymusić wypowiedzenie wszystkich pracowników w ThreadPoolExecutor natychmiast

Dzięki

+0

Dlaczego nie (lub nie możesz) użyć 'shtudown()' lub 'shutdownNow()'? To jest sposób na zrobienie tego. – Gray

+0

Ponieważ musi on czekać na zakończenie bieżących zadań przed zakończeniem wątków. Nie zabija natychmiast nici. – deadlock

+0

'shutdown()' czeka na zakończenie bieżących zadań. Właśnie o to chodzi. – Gray

Odpowiedz

10

Nie można bezpiecznie natychmiast zabić wątki. Zadania powinny zamiast tego uwzględniać przerwania i przerwać je, gdy zostaną przerwane. Jeśli użyjesz ThreadPoolExecutor.shutdownNow(), wszystkie uruchomione zadania zostaną przerwane.

Jedyną alternatywą dla wątków w oddzielnym procesie jest wysłanie sygnału, aby zabić proces.

6

shutdown() uczyni tylko ThreadPoolExecutor odrzucić wszystkie nowe zgłosił zadań i usunąć z kolejki (jeśli ThreadPool jest nieograniczona kolejka wykonawca) zadań oczekujących. Urządzenie shutdownNow() wykona dokładnie to samo, a także zadzwoni pod metodę interrupt() z . Tak więc, w swoim sposobie run(), należy go obsłużyć prawidłowo:

try { 
    Thread.sleep(1000); 
} catch (InterruptedException ie) { 
    // Handle the exception, and close resources. 
} 
+1

'shutdown()' nie opróżnia kolejki. – The111

+0

@ The111, aby opróżnić kolejkę, możesz użyć funkcji czyszczenia() – WiredCoder

2

Jeśli można użyć Callable S zamiast Runnable w twoich wątków można spróbować zadzwonić someTask.cancel() pozbyć zadań uruchomionych w czasie shutdownNow() połączenie.

Należy zauważyć, że nie próbowałem tego, więc nie mogę zagwarantować, że będzie działać tak, jak chcesz, ale sądząc z opisu javadoc warto spróbować.

2

Stare pytanie, ale myślę, że możesz przedłużyć ThreadPoolExecutor, aby przechwycić działające odwołanie do wątku przedExecute(). Po wywołaniu metody shutdownNow() możesz zatrzymać() wszystkie uruchomione wątki. Chociaż zdecydowanie zalecałbym poleganie na isInterrupted() w Twoich zadaniach.

Przykładowy kod ->

public class KillableThreadPoolExecutor extends ThreadPoolExecutor { 

    private final Map<Runnable, Thread> executingThreads; 

    public KillableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, String threadNamePrefix) { 
     super(corePoolSize, maximumPoolSize, keepAliveTime, unit, new YoungMemorySafeLinkedBlockingQueue<Runnable>(), ThreadFactories.create(threadNamePrefix)); 
     executingThreads = new HashMap<>(maximumPoolSize); 
    } 

    @Override 
    protected synchronized void beforeExecute(Thread t, Runnable r) { 
     super.beforeExecute(t, r); 
     executingThreads.put(r, t); 
    } 

    @Override 
    protected synchronized void afterExecute(Runnable r, Throwable t) { 
     super.afterExecute(r, t); 
     if(executingThreads.containsKey(r)) { 
      executingThreads.remove(r); 
     } 
    } 

    @Override 
    public synchronized List<Runnable> shutdownNow() { 
     List<Runnable> runnables = super.shutdownNow(); 
     for(Thread t : executingThreads.values()) { 
      t.stop(); 
     } 
     return runnables; 
    } 
} 
2

ThreadPoolExecutor jest ExecutorService. Nie można zatrzymać wszystkich wątków w ExecutorService metodami lub shutdownNow(). Trzeba zadzwonić shutdown(), awaitTermination() i shutdownNow() metod w sekwencji o wdzięcznym zamykania cytowany przez dokumentacją oracle page

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(); 
    } 
} 

Inne opcje:

  1. invokeAll()
  2. CountDownLatch
  3. iterację wszystkich Future.get() dla wszystkich Callable zadań dla osiągnięcia tego samego celu.