2016-03-28 123 views
0

在下面的示例中,我試圖正常地終止兩個線程。消費者線程在休眠時被中斷,應該將isInterrupted標誌設置爲true。然而,對while循環的!Thread.currentThread()。isInterrupted()檢查似乎仍然返回= false,因爲它不終止消費者線程。睡眠時線程中斷

,將下面的代碼粘貼到和IDE檢查:

public class ThreadInterruptExample { 

public static void main(String[] args) throws InterruptedException { 
    LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(1); 
    ThreadInterruptExample ie = new ThreadInterruptExample(); 
    Producer producer = ie.new Producer(queue); 
    Consumer consumer = ie.new Consumer(queue, producer); 
    producer.start(); 
    consumer.start(); 
    Thread.sleep(1000); 
    producer.cancel(); 
    consumer.cancel(); 
} 

class BaseQueue extends Thread { 
    protected final BlockingQueue<String> queue; 

    public BaseQueue(BlockingQueue<String> queue) { 
     this.queue = queue; 
    } 

    public void cancel() { 
     System.out.println(this.getName() + " - Shutting down"); 
     interrupt(); 
    } 
} 

class Producer extends BaseQueue { 
    private final List<String> messages = Arrays.asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", 
      "r", "s", "t", "u", "v", "w", "x", "y", "z"); 

    public Producer(BlockingQueue<String> queue) { 
     super(queue); 
     this.setName("Producer"); 
    } 

    public void run() { 
     try { 
      for (String message : messages) { 
       System.out.println(this.getName() + ": Sending " + message); 
       queue.put(message); 
      } 
     } catch (InterruptedException e) { 
      System.out.println(this.getName() + " - InterruptedException occurred"); 
     } 
    } 
} 

class Consumer extends BaseQueue { 
    private final BaseQueue producer; 

    public Consumer(BlockingQueue<String> queue, BaseQueue producerQueue) { 
     super(queue); 
     this.setName("Consumer"); 
     producer = producerQueue; 
    } 

    @Override 
    public void run() { 
     while (!Thread.currentThread().isInterrupted()) { 
      System.out.println(this.getName() +": Consumer Running"); 
      String message = ""; 
      try { 
       Thread.sleep(1500); 
       message = queue.take(); 
       System.out.println(this.getName() + ": Recevied " + message); 
       if (message.equals("pill")) { 
        producer.cancel(); 
        this.cancel(); 
       } 
      } catch (InterruptedException e) { 
       System.out.print(this.getName() + ": Exception occurred for: " + message); 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

}

回答

3

你丟棄中斷時,你趕上了InterruptedException的。有兩種解決方案。

while (!Thread.currentThread().isInterrupted()) { 
    try { 
     Thread.sleep(1500); 

    } catch (InterruptedException e) { 
     Thread.currentThread.interrupt(); 
    } 
} 

或更簡單的是隻捕獲循環外的異常。

try { 
    while (!Thread.currentThread().isInterrupted()) { 
     Thread.sleep(1500); 
    } 
} catch (InterruptedException e) { 
    Thread.currentThread.interrupt(); 
} 

編輯:我認爲這僅僅是一個鍛鍊,因爲它會簡單得多使用ExecutorService的

public static void main(String[] args) throws InterruptedException { 
    ExecutorService service = Executors.newSingleThreadExecutor(); 

    for (String message : "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z".split(",")) { 
     System.out.println(getThreadName() + ": Sending " + message); 
     service.submit(() -> { 
      System.out.println(getThreadName() + ": Recevied " + message); 
      try { 
       Thread.sleep(500); 
      } catch (InterruptedException e) { 
       System.out.println("--- Interrupted"); 
      } 
     }); 
    } 
    service.shutdown(); 
    service.awaitTermination(1, TimeUnit.SECONDS); 
    service.shutdownNow(); 
} 

public static String getThreadName() { 
    return Thread.currentThread().getName(); 
} 

打印

main: Sending a 
main: Sending b 
main: Sending c 
main: Sending d 
main: Sending e 
main: Sending f 
main: Sending g 
main: Sending h 
main: Sending i 
main: Sending j 
main: Sending k 
main: Sending l 
main: Sending m 
main: Sending n 
main: Sending o 
main: Sending p 
main: Sending q 
main: Sending r 
main: Sending s 
main: Sending t 
main: Sending u 
main: Sending v 
main: Sending w 
main: Sending x 
main: Sending y 
main: Sending z 
pool-1-thread-1: Recevied a 
pool-1-thread-1: Recevied b 
--- Interrupted 
+0

感謝您的替代示例。而你的建議工作。我不明白爲什麼有必要重新打斷消費者的例外情況。我已經調用過一次consumer.cancel() - >它將調用interrupt()。因此爲什麼會拋出異常。爲什麼我必須再次使用它:Thread.currentThread.interrupt(); ? –

+1

@ShivamSinha一旦你觸發一個InterruptedException,信號被清除,這樣Thread就可以用於別的東西了。它假定你已經在'catch'塊中處理了中斷,並且不需要把它留在那個狀態。注意:無法解除中斷。 –

1

正如javadocs

指示

如果此線程在調用Object類的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long ,int),sleep(long)或sleep(long,int)這個類的方法,那麼它的中斷狀態將被清除,並且會收到一個InterruptedException異常。

因此,在您的情況下,當中斷被調用時,客戶正在睡覺,中斷狀態被清除,並且您收到一個InterruptedException,您可以在其中決定下一步該怎麼做。