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

/**
 * lock.lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定(需要等待别的线程释放锁才行),如果已被中断则出现异常
 * @author: xianzhixianzhixian
 * @date: 2019-01-21 21:09
 */
public class ServiceLockInterruptibly {
    public ReentrantLock lock = new ReentrantLock();
    public void waitMethodLock(){
        try {
            lock.lock();
            System.out.println("lock begin "+Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
                String newString = new String();
                Math.random();
            }
            System.out.println("lock end "+Thread.currentThread().getName());
        } finally {
            lock.unlock();
        }
    }

    public void waitMethodLockInterruptibly(){
        try {
            lock.lockInterruptibly(); //这里是非抢占式的,只有等上一个线程释放锁之后,该方法才能去获取锁
            System.out.println("lock begin "+Thread.currentThread().getName());
            for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
                String newString = new String();
                Math.random();
            }
            System.out.println("lock end "+Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

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获得锁并继续执行。

Java多线程问题--方法lock.lockInterruptibly()、tryLock()和tryLock(long timeout,TimeUint uint)的用法和区别_第1张图片

 

 

 

你可能感兴趣的:(Java,多线程)