-
線程阻塞狀態與等待狀態(當一個線程處於被阻塞或等待狀態時,它暫時不活動,不允許任何代碼且消耗最少的資源)
-
當一個線程試圖獲得一個內部的對象鎖(而不是java.util.concurrent庫中的鎖),而該鎖被其他線程持有,則該線程進入 阻塞狀態
-
當一個線程等待另一個線程通知調度器的一個條件時,它自己進入 等待狀態。在調用Object.wait方法或Thread.join方法,或者是等待java.util.concurrent庫中的Lock或Condition時,就會出現這種情況。 實際上被阻塞狀態與等待狀態是有很大不同的
-
帶有超時參數的方法,調用它們線程會進入 計時等待狀態。這一狀態將一直保持到超時期滿或者接收到適合的通知。帶有超時的方法有Thread.sleep、Object.wait、Thread.join、Lock.tryLock、Condition.await
-
沒有強制線程終止的方法。然而Interrupt方法可以用來請求終止線程,當對一個線程調用interrupt方法時,線程的 中斷狀態被置位,這是每一個線程都有的boolean狀態,每個線程應該不是的檢查這個標志,以判斷線程是否被中斷。當一個線程的中斷狀態被置位時,被中斷的線程決定如何響應中斷
-
intrrupt方法,用來中斷線程
-
interrupted是一個靜態方法,它檢測當前線程是否被中斷。而且, 該方法會清除該線程的中斷狀態,重置中斷狀態為false
-
isInterrupted是一個實例方法,檢驗是否有線程被中斷,不會改變中斷狀態
-
線程中斷時拋出InterruptedException異常解析
-
當一個線程調在sleep方法時,如果在該線程上調用interrupt方法, 將拋出異常
-
當一個線程進入一個同步阻塞( synchronize(o))的等待集wait時,調用interrupt方法, 將拋出異常
-
當線程等待concurrent庫中鎖Lock時, 被中斷不拋異常
-
當線程進入concurrent庫中條件等待集await時, 被中斷不拋異常
-
如果在中斷狀態被置位時調用sleep方法,不會休眠, 反而會清除這一狀態(!)並拋出InterruptException異常
-
鎖測試與超時
-
tryLock方法試圖申請一個鎖,在成功獲得鎖后返回true,否則,立即返回false。而且線程可以離開去做其他事情
-
lock方法不能被中斷。如果一個線程在等待獲得一個鎖時被中斷,並不會拋出異常。中斷線程在獲得鎖之前一直處於阻塞狀態。如果出現死鎖,那么,lock方法就無法終止
-
然而,如果調用帶有超時參數的tryLock(1000,TimeUnit.MILLISECONDS),那么如果線程在等待期間被中斷, 將會拋出InterruptedException異常。這是一個非常有用的特性,因為允許程序打破死鎖
// 當一個線程調在sleep方法時,如果在該線程上調用interrupt方法
public class Demo {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(1000);
t.interrupt(); // 拋出異常
}
}
// 當一個線程進入一個同步阻塞( synchronize(o))的等待集wait時
public class Demo {
public Object o = new Object();
public void fun() throws InterruptedException {
synchronized (o) {
o.wait();
}
}
public static void main(String[] args) throws InterruptedException {
Demo demo = new Demo();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
demo.fun();
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(1000);
t.interrupt(); // 拋出異常
}
}
// 當線程等待concurrent庫中鎖Lock時
public class Bank {
private Lock bankLock;
private Condition sufficientFunds;
public Bank() {
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}
public void transfer() throws InterruptedException {
bankLock.lock(); // 線程t2不拋出異常,可能發生同步阻塞,建議使用帶超時的tryLock(1000,TimeUnit.MILLISECONDS),調用interrupt時拋出異常
// if (bankLock.tryLock()) // 線程t2獲取不到鎖,立即離開做其他事情
// if (bankLock.tryLock(3000, TimeUnit.MILLISECONDS)) // 線程t2拋出異常
// {
try {
while (true) {
}
} finally {
bankLock.unlock();
}
// }
}
public static void main(String[] args) throws InterruptedException {
Bank bank = new Bank();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
bank.transfer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
bank.transfer();
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
Thread.sleep(2000);
t2.interrupt();
}
}
// 當線程進入concurrent庫中條件等待集await時
public class Bank {
private Lock bankLock;
private Condition sufficientFunds;
public Bank() {
bankLock = new ReentrantLock();
sufficientFunds = bankLock.newCondition();
}
public void transfer(boolean b,boolean c) throws InterruptedException {
bankLock.lock();
try {
if (b)
sufficientFunds.await();
while (c) {
}
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Bank bank = new Bank();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
bank.transfer(true,false);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
bank.transfer(false,true);
System.out.println("end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
Thread.sleep(2000);
t1.interrupt();
}
}
