2017-06-22 2 views
0

Ich habe eine pausable Thread-Pool-Executor-Implementierung genau wie in der Dokumentation der ThreadPoolExecutor-Klasse. Ich habe einen einfachen Test, die die folgenden:Warum wird ein Runnable in einem pausierbaren Thread Pool Executor ausgeführt, nachdem der Executor heruntergefahren wurde?

class PausableThreadPoolExecutor extends ThreadPoolExecutor { 
    public static PausableThreadPoolExecutor newSingleThreadExecutor() { 
    return new PausableThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, 
     new LinkedBlockingQueue<Runnable>()); 
    } 

    /** isPaused */ 
    private boolean isPaused; 

    /** pauseLock */ 
    private ReentrantLock pauseLock = new ReentrantLock(); 

    /** unpaused */ 
    private Condition unpaused = this.pauseLock.newCondition(); 

    public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
     TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 
    } 

    @Override 
    protected void beforeExecute(Thread t, Runnable r) { 
    super.beforeExecute(t, r); 
    this.pauseLock.lock(); 
    try { 
     while (this.isPaused) { 
     this.unpaused.await(); 
     } 
    } catch (InterruptedException ie) { 
     t.interrupt(); 
    } finally { 
     this.pauseLock.unlock(); 
    } 
    } 

    public void pause() { 
    this.pauseLock.lock(); 
    try { 
     this.isPaused = true; 
    } finally { 
     this.pauseLock.unlock(); 
    } 
    } 

    public void resume() { 
    this.pauseLock.lock(); 
    try { 
     this.isPaused = false; 
     this.unpaused.signalAll(); 
    } finally { 
     this.pauseLock.unlock(); 
    } 
    } 

    public static void main(String[] args) { 
    PausableThreadPoolExecutor p = PausableThreadPoolExecutor.newSingleThreadExecutor(); 
    p.pause(); 
    p.execute(new Runnable() { 

     public void run() { 
     for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { 
      System.out.println(ste); 
     } 
     } 
    }); 
    p.shutdownNow(); 
    } 
} 

Interessanterweise ist der Aufruf an shutDownNow wird die Runnable verursachen laufen. Ist das normal? Wie ich es verstehe, wird die shutDownNow versuchen, die aktiv ausgeführten Aufgaben zu stoppen, indem sie unterbrochen werden. Aber der Interrupt scheint die Aufgabe aufzuwecken und auszuführen. Kann jemand das erklären?

+0

, wenn Sie für das Herunterfahren nennen, ist es der worker-Thread unterbrechen, die es nicht bedeuten, stoppt sofort .Es hängt die Logik und wie Sie verwenden inter zerreißen Flagge in Ihrem Code –

Antwort

1

Interessanterweise führt der Aufruf von shutDownNow dazu, dass Runnable ausgeführt wird. Ist das normal?

Nicht sicher, dass es "normal" ist, aber es ist sicherlich mit Ihrem Code erwartet. In Ihrer beforeExecute(...) Methode sehe ich folgende:

this.pauseLock.lock(); 
    try { 
     while (this.isPaused) { 
      this.unpaused.await(); 
     } 
    } catch (InterruptedException ie) { 
     t.interrupt(); 
    } finally { 
     this.pauseLock.unlock(); 
    } 

Der Auftrag für den isPaused boolean wartet LOPP auf false gesetzt werden. Wenn der Job jedoch unterbrochen wird, wirft der this.unpaused.await()InterruptedException, der aus der while-Schleife ausbricht, der Thread wird erneut unterbrochen, was immer ein gutes Muster ist, beforeExecute() zurückgibt, und der Auftrag darf ausgeführt werden. Das Unterbrechen eines Threads führt nicht zu einem Abbruch, es sei denn, Sie verfügen über einen spezifischen Code für die Unterbrechung.

Wenn Sie den Job beenden, wenn es unterbrochen wird, dann könnte man ein RuntimeException im beforeExecute() Handler werfen, wenn Sie sehen, dass der Job als unterbrochen:

} catch (InterruptedException ie) { 
    t.interrupt(); 
    throw new RuntimeException("Thread was interrupted so don't run"); 

Ein sauberer Ansatz könnte zu prüfen sein, sehen, wenn Sie in der run() Verfahren unterbrochen werden und dann die Ausfahrt:

public void run() { 
    if (Thread.currentThread().isInterrupted()) { 
     return; 
    } 
    ... 
+0

Klar, danke für die Antwort. –

Verwandte Themen