interrupt
1. 在sleep時如果這個線程發生中斷,也只是將堵塞狀態變為非堵塞狀態
package info;import java.util.concurrent.*; public class Factory implements Runnable{public void run() {System.out.println("begin run");while(true) {try {System.out.println("sleeping");Thread.sleep(1000);}catch(InterruptedException e) {System.out.println("catch interrupt");e.printStackTrace();}}}public static void main(String[] args) {Thread t = new Thread(new Factory());t.start();try {Thread.sleep(2000);}catch(InterruptedException e) {System.out.println("main interrupt");}System.out.println("main thread excute t interrupt");t.interrupt();}}output:
begin run
sleeping
sleeping
main thread excute t interrupt
sleeping
catch interrupt
java.lang.InterruptedException: sleep interruptedsleeping
at java.lang.Thread.sleep(Native Method)
at info.Factory.run(Factory.java:11)
at java.lang.Thread.run(Unknown Source)
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
sleeping
被catch了,只是將這個線程從堵塞狀態變為非堵塞狀態,并死循環
如果將代碼修改為
public void run() {System.out.println("begin run");while(!Thread.interrupted()) {try {System.out.println("sleeping");Thread.sleep(2000);}catch(InterruptedException e) {System.out.println("catch interrupt");System.out.println("thread is interrupted ? " + Thread.interrupted());e.printStackTrace();}}}output:
begin run
sleeping
sleeping
main thread excute t interrupt
catch interrupt
thread is interrupted ? false
java.lang.InterruptedException: sleep interruptedsleeping
at java.lang.Thread.sleep(Native Method)
at info.Factory.run(Factory.java:11)
at java.lang.Thread.run(Unknown Source)
sleeping
sleeping
sleeping
還是死循環,雖然發生了中斷,但是interrupted的中斷位還是false,這是因為在拋出異常時候,自動將其設為了false
將代碼修改如下,就可以了
public void run() {System.out.println("begin run");while(!Thread.interrupted()) {try {System.out.println("sleeping");Thread.sleep(2000);}catch(InterruptedException e) {System.out.println("catch interrupt");System.out.println("thread is interrupted ? " + Thread.interrupted());Thread.currentThread().interrupt();e.printStackTrace();}}}?對于非阻塞中的線程, 只是改變了中斷狀態, 即Thread.Interrupted()將返回true; 對于可取消的阻塞狀態中的線程, 比如等待在這些函數上的線程, Thread.sleep(), Object.wait(), Thread.join(), 這個線程收到中斷信號后, 會拋出InterruptedException, 同時會把中斷狀態置回為false.
public void run() {System.out.println("begin run");while(!Thread.interrupted()) {System.out.println("sleeping");}}
通用的寫法,不論是否是堵塞,應該這樣寫
public void run() {System.out.println("begin run");try {while(!Thread.interrupted()) {System.out.println("sleeping");//如果在這句話,就是非堵塞的時候收到中斷信號,那么其interrupted變為true,在下次循環判斷時就退出Thread.sleep(2000); //如果在這句話,也就是在堵塞的時候收到中斷信號,那么就會拋出一個異常,interrupted在拋出異常時又變為false}}catch(InterruptedException e) {System.out.println("catch interrupt");}}
看到一個例子,可以比較好的展現interrupt的機制
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock;public class test {/*** @param args*/private ReentrantLock lock = new ReentrantLock();public Runnable createTask() {return new Runnable() {public void run() {while (true) {try {lock.lock();{//if(lock.tryLock()) {//if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {try {System.out.println("locked "+Thread.currentThread().getName());System.out.println("begin sleep "+Thread.currentThread().getName());Thread.sleep(10000);System.out.println("end sleep "+Thread.currentThread().getName());} finally {lock.unlock();System.out.println("unlock "+Thread.currentThread().getName());}break;} // else { // System.out.println("unable to lock "+Thread.currentThread().getName()); // }} catch(InterruptedException e) {System.out.println("interrupted "+Thread.currentThread().getName());}}//while}};}public static void main(String[] args)throws Exception {test t = new test();Thread t1 = new Thread(t.createTask(), "T1");Thread t2 = new Thread(t.createTask(), "T2");t1.start();t2.start();Thread.sleep(600);t2.interrupt();}}output:
locked T1
begin sleep T1
end sleep T1
unlock T1
locked T2
begin sleep T2
unlock T2
interrupted T2
locked T2
begin sleep T2
end sleep T2
unlock T2
T1線程先得到所,就睡眠了10秒,T2就堵塞了10秒,在這10秒內主線程對T2發出了一個interrupt消息,但是因為T2在等待鎖的過程中,是不會響應中斷信號的。
10秒之后,T2獲得了鎖,注意調用線程interrupt的唯一作用就是將線程內部的interruption變量變為了ture,但是一旦線程進入不是因為等待鎖而導致的堵塞時,發現這個變量是ture, 這時就產生了一個interruption中斷,但是注意這里finally的作用,即使有異常了,但是也得必須運行finally塊內部的代碼,然后再跳到外層的catch中。
如果調用線程的.isInterrupted()函數,就會顯示是否有中斷,然后在把中斷變量設為false.
如果將16行改為lock.lockInterruptibly(); 就是T2在等待鎖的過程中,也會響應中斷信號。
tryLock在等待鎖的時候也會響應中斷
看看這個程序有什么問題?
public class SemaphoreTest extends Thread {Semaphore position;private int id;public SemaphoreTest(int i, Semaphore s) {this.id = i;this.position = s;}public void run() {try {if (position.availablePermits() > 0) {System.out.println("顧客[" + id + "]進入廁所,有空位");} else {System.out.println("顧客[" + id + "]進入廁所,沒空位,排隊");}position.acquire(); System.out.println("【" + id + "】acquire坑位");Thread.sleep((int) (Math.random() * 1000));System.out.println("【" + id + "】完畢release");position.release(); }catch (Exception e) {e.printStackTrace();}}public static void main(String args[]) {ExecutorService pool = Executors.newCachedThreadPool();Semaphore position = new Semaphore(2); // 初始化兩個空位for (int i = 0; i < 5; i++) {pool.submit(new SemaphoreTest(i, position));}System.out.println("開始釋放線程池資源");pool.shutdownNow();System.out.println("完成釋放線程池資源");position.acquireUninterruptibly(2); System.out.println("如廁完畢,清理廁所");position.release(2); } }
但是堵塞著的程序并沒有finally塊來釋放semaphore,導致主線程死等
總結
- 上一篇: ant教程
- 下一篇: 安装ubuntu 13.04