本文內容部分引自《Java多線程編程核心技術》,感謝作者!!!
代碼地址:https://github.com/xianzhixianzhixian/thread.git
方法lock.lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUint uint)的用法和區別
1、lock.lockInterruptibly()的作用是:如果當前線程未被中斷,則獲取鎖定(需要等待別的線程釋放鎖才行),如果已被中斷則出現異常。但是使用lock.lock()時,當前線程被中斷,不會報錯。
2、lock.tryLock()和lock.tryLock(Long timeout,TimeUnit unit)的作用
lock.tryLock()的作用是:僅在調用時鎖定未被另一個線程保持的情況下,才獲取該鎖定,否則就不獲取。就是說只會去獲取未被鎖定的線程。
lock.tryLock(long timeout,TimeUnit unit)的作用是:如果給定線程在等待時間內未被另一個線程保持,且當前線程未被中斷,則獲取該鎖定,否則就不獲取,相當於tryLock()加了等待時間。
方法lock.lockInterruptibly()使用示例
ServiceLockInterruptibly.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-21 21:22
*/
public class RunServiceLockInterruptibly {
public static void main(String[] args) throws Exception {
final ServiceLockInterruptibly serviceLockInterruptibly = new ServiceLockInterruptibly();
Runnable runnable0 = new Runnable() {
@Override
public void run() {
serviceLockInterruptibly.waitMethodLock();
}
};
Runnable runnable1 = new Runnable() {
@Override
public void run() {
serviceLockInterruptibly.waitMethodLockInterruptibly();
}
};
Thread threadA = new Thread(runnable0);
threadA.setName("A");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(runnable0);
threadB.setName("B");
threadB.start();
/**
* 此處中斷threadB線程,看看結果會怎麼樣,不會出現異常,使用的是lock.lock()方法。
* 爲什麼B線程interrupt之後還能執行lock end B呢,因爲僅僅靠thread.interrupt()是無法中斷線程的,需要結合拋異常使用
* 才行,"異常法終止線程運行"。
*/
threadB.interrupt();
Thread threadC = new Thread(runnable1);
threadC.setName("C");
threadC.start();
threadC.interrupt(); //此處中斷threadC線程,看看結果會怎麼樣,會出現異常,使用的是lock.lockInterruptibly()方法
System.out.println("main end");
}
RunServiceLockInterruptibly.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-21 21:22
*/
public class RunServiceLockInterruptibly {
public static void main(String[] args) throws Exception {
final ServiceLockInterruptibly serviceLockInterruptibly = new ServiceLockInterruptibly();
Runnable runnable0 = new Runnable() {
@Override
public void run() {
serviceLockInterruptibly.waitMethodLock();
}
};
Runnable runnable1 = new Runnable() {
@Override
public void run() {
serviceLockInterruptibly.waitMethodLockInterruptibly();
}
};
Thread threadA = new Thread(runnable0);
threadA.setName("A");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(runnable0);
threadB.setName("B");
threadB.start();
threadB.interrupt(); //此處中斷threadB線程,看看結果會怎麼樣,不會出現異常,使用的是lock.lock()方法
Thread threadC = new Thread(runnable1);
threadC.setName("C");
threadC.start();
threadC.interrupt(); //此處中斷threadC線程,看看結果會怎麼樣,會出現異常,使用的是lock.lockInterruptibly()方法
System.out.println("main end");
}
}
運行結果:threadA和threadB使用的是lcok.lock(),threadC使用的是lock.lockInterruptibly()方法。threadA沒有被中斷,從頭到尾執行完成。threadB被中斷,沒有拋出異常。但是爲什麼lock end B還會被執行呢?因爲僅僅靠thread.interrupt()是無法中斷線程的,需要結合拋異常使用才行,"異常法終止線程運行"。threadC在執行的時候被中斷,拋出異常了。
tryLock()和tryLock(long timeout,TimeUint uint)使用示例
ServiceTryLock.java
/**
* lock.tryLock()和lock.tryLock(Long timeout,TimeUnit unit)的作用
* lock.tryLock()的作用是:僅在調用時鎖定未被另一個線程保持的情況下,才獲取該鎖定,否則就不獲取。就是說只會去獲取未被鎖定的線程
* lock.tryLock(long timeout,TimeUnit unit)的作用是:如果給定線程在等待時間內未被另一個線程保持,且當前線程未被中斷,則獲取該鎖定,否則就不獲取。相當於tryLock()加了等待時間
* @author: xianzhixianzhixian
* @date: 2019-01-21 21:10
*/
public class ServiceTryLock {
public ReentrantLock lock = new ReentrantLock();
public void waitMethodTryLock(){
try {
if (lock.tryLock()){
System.out.println(Thread.currentThread().getName()+"獲得鎖");
} else {
System.out.println(Thread.currentThread().getName()+"沒有獲得鎖");
}
} finally {
if (lock.isHeldByCurrentThread()){
lock.unlock();
}
}
}
public void waitMethodTryLockTime(){
try {
if(lock.tryLock(3, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName()+"獲得鎖的時間:"+System.currentTimeMillis());
} else {
System.out.println(Thread.currentThread().getName()+"沒有獲得鎖");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()){
lock.unlock();
System.out.println(Thread.currentThread().getName()+"釋放鎖的時間:"+System.currentTimeMillis());
}
}
}
}
RunTryLock.java
/**
* @author: xianzhixianzhixian
* @date: 2019-01-21 21:38
*/
public class RunTryLock {
public static void main(String[] args) throws Exception {
final ServiceTryLock serviceTryLock = new ServiceTryLock();
Runnable runnable0 = new Runnable() {
@Override
public void run() {
serviceTryLock.waitMethodTryLock();
}
};
Thread threadA = new Thread(runnable0);
threadA.setName("A");
threadA.start();
Thread threadB = new Thread(runnable0);
threadB.setName("B");
threadB.start();
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"調用waitMethodTryLockTime的時間:"+System.currentTimeMillis());
serviceTryLock.waitMethodTryLockTime();
}
};
Thread threadC = new Thread(runnable1);
threadC.setName("C");
threadC.start();
//Thread.sleep(3000);
Thread threadD = new Thread(runnable1);
threadD.setName("D");
threadD.start();
}
}
運行結果:threadA和threadB使用的是lock.tryLock(),threaC和threadD使用的是lock.tryLock(long,TimeUnit)。threadA先獲得鎖,而threadB在探測到threadA獲得鎖之後就不去獲得鎖了,所以顯示“A獲得鎖,B未獲得鎖”。threadC和threadD都是等待3秒後再去檢測鎖是否被獲得,threadC獲得鎖執行完之後3秒還未過去,此時threadD檢測到threadC釋放鎖且等待時間未超過3秒,threadD獲得鎖並繼續執行。