lockInterruptibly() 方法的作用:如果當前線程未被中斷則獲得鎖,如果當前線程被中斷則出現異常。
package com.wkcto.lock.reentrant;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* lockInterruptibly() 方法的作用:如果當前線程未被中斷則獲得鎖,如果當前線程被中斷則出現異常.
*/
public class Test05 {
static class Servier{
private Lock lock = new ReentrantLock(); //定義鎖對象
public void serviceMethod(){
try {
// lock.lock(); //獲得鎖定,即使調用了線程的interrupt()方法,也沒有真正的中斷線程
lock.lockInterruptibly(); //如果線程被中斷了,不會獲得鎖,會產生異常
System.out.println(Thread.currentThread().getName() + "-- begin lock");
//執行一段耗時的操作
for (int i = 0; i < Integer.MAX_VALUE; i++) {
new StringBuilder();
}
System.out.println( Thread.currentThread().getName() + " -- end lock");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println( Thread.currentThread().getName() + " ***** 釋放鎖");
lock.unlock(); //釋放鎖
}
}
}
public static void main(String[] args) throws InterruptedException {
Servier s = new Servier();
Runnable r = new Runnable() {
@Override
public void run() {
s.serviceMethod();
}
};
Thread t1 = new Thread(r);
t1.start();
Thread.sleep(50);
Thread t2 = new Thread(r);
t2.start();
Thread.sleep(50);
t2.interrupt(); //中斷t2線程
}
}
對于synchronized內部鎖來說,如果一個線程在等待鎖,只有兩個結果:要么該線程獲得鎖繼續執行;要么就保持等待。
對于ReentrantLock可重入鎖來說,提供另外一種可能,在等待鎖的過程中,程序可以根據需要取消對鎖的請求。
package com.wkcto.lock.reentrant;
import com.wkcto.pipestream.Test2;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 通過ReentrantLock鎖的lockInterruptibly()方法避免死鎖的產生
*/
public class Test06 {
static class IntLock implements Runnable{
//創建兩個ReentrantLock 鎖對象
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lockNum; //定義整數變量,決定使用哪個鎖
public IntLock(int lockNum) {
this.lockNum = lockNum;
}
@Override
public void run() {
try {
if ( lockNum % 2 == 1){ //奇數,先鎖1,再鎖2
lock1.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "獲得鎖1,還需要獲得鎖2");
Thread.sleep(new Random().nextInt(500));
lock2.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "同時獲得了鎖1與鎖2....");
}else { //偶數,先鎖2,再鎖1
lock2.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "獲得鎖2,還需要獲得鎖1");
Thread.sleep(new Random().nextInt(500));
lock1.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "同時獲得了鎖1與鎖2....");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if ( lock1.isHeldByCurrentThread()) //判斷當前線程是否持有該鎖
lock1.unlock();
if (lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println( Thread.currentThread().getName() + "線程退出");
}
}
}
public static void main(String[] args) throws InterruptedException {
IntLock intLock1 = new IntLock(11);
IntLock intLock2 = new IntLock(22);
Thread t1 = new Thread(intLock1);
Thread t2 = new Thread(intLock2);
t1.start();
t2.start();
//在main線程,等待3000秒,如果還有線程沒有結束就中斷該線程
Thread.sleep(3000);
//可以中斷任何一個線程來解決死鎖, t2線程會放棄對鎖1的申請,同時釋放鎖2, t1線程會完成它的任務
if (t2.isAlive()){ t2.interrupt();}
}
}