Java多線程問題--方法lock.lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUint uint)的用法和區別

本文內容部分引自《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獲得鎖並繼續執行。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章