Thread包含interrupt()方法,所以你能夠終止被阻塞的任務,這個方法將設置線程的中斷狀態。若是一個線程已經被阻塞,或者試圖執行一個阻塞操做。那麼設置這個線程的中斷狀態將java
拋出InterruptedException。當拋出改異常或者該任務調用Thread.interrupted()時,中斷狀態將被複位。git
查看Thread的API,關於中斷的方法有:併發
void interrupt() interrupts this threadapp
static boolean interrupted() Test whether the current thread has been interruptedide
boolean isInterrupted() Test whether the current thread has been interrupted高併發
經過幾個例子看一下中斷的用法和特色:ui
例子一,分別模擬了,中斷線程sleep,I/O和synchronized修飾的方法。結論:調用interrupt()方法,只有sleep的線程能夠被中斷,I/O和用synchronized修飾的線程是不能被中斷的this
public class Interrupting { private static ExecutorService service = Executors.newCachedThreadPool(); static void test(Runnable r) throws InterruptedException{ Future<?> f = service.submit(r); TimeUnit.MILLISECONDS.sleep(100); System.out.println("Interrupting: " + r.getClass().getName()); f.cancel(true); //interrupts if running System.out.println("interrupted send to: " + r.getClass().getName()); } public static void main(String[] args) throws Exception{ // test(new SleepBlocked()); // test(new IOBlocked(System.in)); test(new SynchronizedBlocked()); TimeUnit.SECONDS.sleep(10); System.out.println("Aborting with System.exit(0)"); System.exit(0); } } class SleepBlocked implements Runnable { @Override public void run() { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { System.out.println("InterruptedException"); } System.out.println("Exiting SleepBlocked.run()"); } } class IOBlocked implements Runnable { private InputStream is; public IOBlocked(InputStream is) { this.is = is; } @Override public void run() { try { System.out.print("waiting for read:"); is.read(); } catch (IOException e) { if(Thread.currentThread().isInterrupted()) { System.out.println("Interrupted IO Blocked"); } else { throw new RuntimeException(e); } } System.out.println("Exiting IOBlocked.run()"); } } class SynchronizedBlocked implements Runnable { public SynchronizedBlocked() { new Thread(){ @Override public void run() { f(); } }.start(); } public synchronized void f() { while(true) { //Never release lock Thread.yield(); } } @Override public void run() { System.out.println("try to call f()"); f(); System.out.println("Exiting SynchronizedBlocked.run()"); } }
例子二,sleep是能夠被中斷的,中斷後,中斷標識位「復位」spa
package org.burning.sport.javase.thread.interrupt; import java.util.concurrent.TimeUnit; public class InterruptSleep implements Runnable{ @Override public void run() { try { while (true) { System.out.println("開始睡了"); TimeUnit.SECONDS.sleep(3); } } catch (InterruptedException e) { boolean isInterrupt = Thread.interrupted(); //中斷狀態被複位 System.out.println("中斷狀態:" + isInterrupt); } } public static void main(String[] args) throws Exception{ Thread t = new Thread(new InterruptSleep()); t.start(); TimeUnit.SECONDS.sleep(5); t.interrupt(); System.out.println("interrupted is: " + t.isInterrupted()); } } /* 開始睡了 開始睡了 interrupted is: false 中斷狀態:false */
例子三,普通方法是中斷不了的,而且從最後的輸出結果 interrupted is: true 看出中斷標識位沒有被清除。線程
package org.burning.sport.javase.thread.interrupt; import java.util.concurrent.TimeUnit; public class InterruptCommonTest implements Runnable{ @Override public void run() { while (true) { System.out.println("你中斷一個試試"); boolean interrupt = Thread.interrupted(); System.out.println("中斷狀態" + interrupt); } } public static void main(String[] args) throws Exception{ Thread t = new Thread(new InterruptCommonTest()); t.setDaemon(true); t.start(); TimeUnit.SECONDS.sleep(5); t.interrupt(); System.out.println("interrupted is: " + t.isInterrupted()); } } /* 中斷狀態false 你中斷一個試試 中斷狀態false 你中斷一個試試 中斷狀態false interrupted is: true 你中斷一個試試 中斷狀態false */
總結:你可以中斷對sleep的調用(或者任何要求拋出InterruptedException的調用)。可是你不能中斷正在試圖獲取synchronized鎖或者正在試圖執行IO操做的線程
例子四:Lock與中斷的關係。
上面的例子中看到,synchronized是不能被中斷的,可是Lock是能夠被中斷的。這個算是synchronized和Lock的不一樣點。查看Lock的API,有一個方法
void lockInterruptibly() throws InrruptedException 就是能夠被中斷的方式來獲取鎖的方法。
package org.burning.sport.javase.thread.interrupt; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; public class InterruptLockTest implements Runnable{ private static ReentrantLock lock = new ReentrantLock(); @Override public void run() { try { lock.lockInterruptibly(); while(true) { Thread.yield(); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) throws Exception{ InterruptLockTest lockTest = new InterruptLockTest(); Thread t1 = new Thread(lockTest); Thread t2 = new Thread(lockTest); t1.start(); t2.start(); TimeUnit.SECONDS.sleep(3); t2.interrupt(); System.out.println("結束..."); } } /* 結束... java.lang.InterruptedException at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898) at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at org.burning.sport.javase.thread.interrupt.InterruptLockTest.run(InterruptLockTest.java:18) at java.lang.Thread.run(Thread.java:745) Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261) at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457) at org.burning.sport.javase.thread.interrupt.InterruptLockTest.run(InterruptLockTest.java:25) at java.lang.Thread.run(Thread.java:745) */
https://gitee.com/play-happy/base-project
參考:
【1】《Think in Java》,21.3.4 中斷
【2】《Java 高併發程序設計》,2.2.3 線程中斷