ReentrantLock的相关方法使用
获取锁定
- void lock():常用获取锁定的方法
- void lockInterruptibly():如果当前线程未被中断,则获取锁定;如果当前线程被中断,则出现异常
- boolean tryLock():调用时锁定未被另一个线程持有的情况下,才会获取该锁定
- boolean tryLock(long timeOut,TimeUnit unit):如果锁定在给定时间内未被另一个线程持有,且当前线程未被中断,则获取该锁定
lock()方法
1 public class Run { 2 private ReentrantLock lock = new ReentrantLock(); 3 4 public void testLock(){ 5 try { 6 lock.lock(); 7 8 for (int i = 0; i < 5; i++) { 9 System.out.println("ThreadName = "+Thread.currentThread().getName()+", i = "+(i+1)); 10 } 11 System.out.println(Thread.currentThread().getName()+"线程执行完毕,当前时间:"+System.currentTimeMillis()); 12 Thread.sleep(1000); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } finally { 16 lock.unlock(); 17 } 18 } 19 public static void main(String[] args) { 20 Run run = new Run(); 21 run.testLock(); 22 23 Runnable runnable = new Runnable() { 24 @Override 25 public void run() { 26 run.testLock(); 27 } 28 }; 29 Thread threadA = new Thread(runnable); 30 threadA.setName("A"); 31 threadA.start(); 32 Thread threadB = new Thread(runnable); 33 threadB.setName("B"); 34 threadB.start(); 35 } 36 }
----------------------------------------------------console----------------------------------------------------
ThreadName = main, i = 1 ThreadName = main, i = 2 ThreadName = main, i = 3 ThreadName = main, i = 4 ThreadName = main, i = 5 main线程执行完毕,当前时间:1539138509575 ThreadName = A, i = 1 ThreadName = A, i = 2 ThreadName = A, i = 3 ThreadName = A, i = 4 ThreadName = A, i = 5 A线程执行完毕,当前时间:1539138510587 ThreadName = B, i = 1 ThreadName = B, i = 2 ThreadName = B, i = 3 ThreadName = B, i = 4 ThreadName = B, i = 5 B线程执行完毕,当前时间:1539138511587
lockInterruptibly()方法
1 public class Run2 { 2 private ReentrantLock lock = new ReentrantLock(); 3 public void testLockInterruptibly(){ 4 try { 5 lock.lockInterruptibly(); 6 System.out.println("ThreadName = "+Thread.currentThread().getName()); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } finally { 10 if(lock.isHeldByCurrentThread()){//查询当前线程是否保持锁定 11 lock.unlock(); 12 } 13 } 14 } 15 16 public static void main(String[] args) { 17 Run2 run2 = new Run2(); 18 Runnable runnable = new Runnable() { 19 @Override 20 public void run() { 21 run2.testLockInterruptibly(); 22 } 23 }; 24 Thread t1 = new Thread(runnable); 25 t1.setName("T1"); 26 t1.start(); 27 28 Thread t2 = new Thread(runnable); 29 t2.setName("T2"); 30 t2.start(); 31 t2.interrupt(); 32 } 33 }
----------------------------------------------------console----------------------------------------------------
java.lang.InterruptedException ThreadName = T1 at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220) at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) at com.qf.test12.t.Run2.testLockInterruptibly(Run2.java:13) at com.qf.test12.t.Run2$1.run(Run2.java:29) at java.lang.Thread.run(Thread.java:748)
tryLock()方法
1 public class Run3 { 2 private ReentrantLock lock = new ReentrantLock(); 3 public void testTryLock(){//只获取锁定,不释放锁定 4 if(lock.tryLock()){ 5 System.out.println(Thread.currentThread().getName()+"获得锁"); 6 }else { 7 System.out.println(Thread.currentThread().getName()+"未获得锁"); 8 } 9 } 10 11 public static void main(String[] args) { 12 Run3 run3 = new Run3(); 13 Runnable runnable = new Runnable() { 14 @Override 15 public void run() { 16 run3.testTryLock(); 17 } 18 }; 19 Thread threadA = new Thread(runnable); 20 threadA.setName("A"); 21 threadA.start(); 22 Thread threadB = new Thread(runnable); 23 threadB.setName("B"); 24 threadB.start(); 25 } 26 }
----------------------------------------------------console----------------------------------------------------
A获得锁
B未获得锁
tryLock(long timeOut,TimeUnit unit)方法
1 public class Run3 { 2 private ReentrantLock lock = new ReentrantLock(); 3 public void testTryLock(){ 4 try { 5 if(lock.tryLock(3, TimeUnit.SECONDS)){ 6 System.out.println(Thread.currentThread().getName()+"获得锁"); 7 Thread.sleep(4000);//有一个未获得锁 8 //Thread.sleep(2000);//两个都获得锁 9 }else { 10 System.out.println(Thread.currentThread().getName()+"未获得锁"); 11 } 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } finally { 15 if(lock.isHeldByCurrentThread()){ 16 lock.unlock(); 17 } 18 } 19 } 20 21 public static void main(String[] args) { 22 Run3 run3 = new Run3(); 23 Runnable runnable = new Runnable() { 24 @Override 25 public void run() { 26 System.out.println(Thread.currentThread().getName()+"执行,当前时间:"+System.currentTimeMillis()); 27 run3.testTryLock(); 28 } 29 }; 30 Thread threadA = new Thread(runnable); 31 threadA.setName("A"); 32 threadA.start(); 33 Thread threadB = new Thread(runnable); 34 threadB.setName("B"); 35 threadB.start(); 36 } 37 }
----------------------------------------------------console----------------------------------------------------
--------------------Thread.sleep(4000)------------------- A执行,当前时间:1539141085501 B执行,当前时间:1539141085501 B获得锁 A未获得锁 --------------------Thread.sleep(2000)------------------- A执行,当前时间:1539141269380 B执行,当前时间:1539141269380 A获得锁 B获得锁
其他常用方法
getXxx方法
- int getHoldCount()方法:查询当前线程保持此锁定的个数,即当前线程调用lock()方法的次数
- int getQueueLength()方法:返回正在等待此锁定的线程估计数
- int getWaitQueueLength(Condition condition)方法:返回等待与此锁定相关的给定条件的线程估计数
hasXxx方法
- boolean hasQueuedThread(Thread thread)方法:查询指定线程是否正在等待获取此锁定
- boolean hasQueuedThreads()方法:查询是否有线程正在等待此锁定
- boolean hasWaiters(Condition condition)方法:查询是否有线程正在等待与此锁定有关的condition条件
isXxx方法
- boolean isFair()方法:判断是不是公平锁
- boolean isHeldByCurrentThread()方法:查询当前线程是否保持此锁定
- boolean isLocked()方法:判断此锁定是否由任意线程保持
Condition的几个方法
- awaitUninterruptibly()方法:调用该方法的前提是,当前线程已经成功获得与该条件对象绑定的重入锁,否则调用该方法时会抛出IllegalMonitorStateException。调用该方法后,结束等待的唯一方法是其它线程调用该条件对象的signal()或signalALL()方法。等待过程中如果当前线程被中断,该方法仍然会继续等待,同时保留该线程的中断状态。
- awaitNanos(long nanosTimeout) 方法:调用该方法的前提是,当前线程已经成功获得与该条件对象绑定的重入锁,否则调用该方法时会抛出IllegalMonitorStateException。nanosTimeout指定该方法等待信号的的最大时间(单位为纳秒)。若指定时间内收到signal()或signalALL()则返回nanosTimeout减去已经等待的时间;若指定时间内有其它线程中断该线程,则抛出InterruptedException并清除当前线程的打断状态;若指定时间内未收到通知,则返回0或负数
- awaitUntil(Date deadline) 方法:适用条件与行为与awaitNanos(long nanosTimeout)完全一样,唯一不同点在于它不是等待指定时间,而是等待由参数指定的某一时刻,等待时间到达前可以被其他线程提前唤醒