• java并发之ReentrantLock学习理解


    简介

    java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路通知分支等功能,并且使用上比synchronized更加灵活。

    如何使用ReentrantLock

    主要是lock.lock()lock.unlock()两个方法

     1 public class MyService implements Runnable {
     2     
     3     protected ReentrantLock lock;
     4     
     5     public MyService(ReentrantLock lock){
     6         this.lock = lock;
     7     }
     8 
     9     public void run() {
    10         lock.lock();
    11         for (int i = 0; i < 5; i++) {
    12             System.out.println(Thread.currentThread().getName()+" "+i);
    13             try {
    14                 Thread.sleep(1000);
    15             } catch (InterruptedException e) {
    16                 e.printStackTrace();
    17             }
    18         }
    19         lock.unlock();
    20     }
    21 
    22 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         ReentrantLock lock = new ReentrantLock();
    10         for (int i = 0; i < 4; i++) {
    11             new Thread(new MyService(lock)).start();
    12         }
    13     }
    14 }
    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
    Thread-2 0
    Thread-2 1
    Thread-2 2
    Thread-2 3
    Thread-2 4
    Thread-3 0
    Thread-3 1
    Thread-3 2
    Thread-3 3
    Thread-3 4
    

    使用Condition类实现wait、notify的功能

    Condition类也是jdk1.5里出来的,它能实现synchronized和wait、notify搭配的功能,另外比后者更灵活,Condition可以实现多路通知功能,也就是在一个Lock对象里可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择的进行线程通知,在调度线程上更加灵活

    而synchronized就相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在这个对象上。线程开始notifyAll时,需要通知所有的WAITING线程,没有选择权,会有相当大的效率问题。

    使用Condition为什么会报java.lang.IllegalMonitorStateException异常

    还是刚才的代码,稍作改动

     1 public class MyService implements Runnable {
     2     
     3     protected ReentrantLock lock;
     4     protected Condition condition;
     5     
     6     public MyService(ReentrantLock lock,Condition condition){
     7         this.lock = lock;
     8         this.condition = condition;
     9     }
    10 
    11     public void run() {
    12 //        lock.lock();
    13         try {
    14             condition.await();
    15         } catch (InterruptedException e1) {
    16             // TODO Auto-generated catch block
    17             e1.printStackTrace();
    18         }
    19         for (int i = 0; i < 5; i++) {
    20             System.out.println(Thread.currentThread().getName()+" "+i);
    21             try {
    22                 Thread.sleep(1000);
    23             } catch (InterruptedException e) {
    24                 e.printStackTrace();
    25             }
    26         }
    27 //        lock.unlock();
    28     }
    29 
    30 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         ReentrantLock lock = new ReentrantLock();
    10         Condition condition = lock.newCondition();
    11         for (int i = 0; i < 4; i++) {
    12             new Thread(new MyService(lock,condition)).start();
    13         }
    14     }
    15 }
    Exception in thread "Thread-0" Exception in thread "Thread-1" Exception in thread "Thread-2" Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
    	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(Unknown Source)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(Unknown Source)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(Unknown Source)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
    	at ww.MyService.run(MyService.java:26)
    	at java.lang.Thread.run(Unknown Source)
    

      报错的异常信息是监视器出错,原因是在调用condition.await()之前是要先调用lock.lock()来获得同步监视器

    正确使用Condition类

     1 public class MyService implements Runnable {
     2     
     3     protected ReentrantLock lock;
     4     protected Condition condition;
     5     
     6     public MyService(ReentrantLock lock,Condition condition){
     7         this.lock = lock;
     8         this.condition = condition;
     9     }
    10     
    11     public void await(){
    12         try {
    13             lock.lock();
    14             System.out.println("await time is "+System.currentTimeMillis());
    15             condition.await();
    16             System.out.println("after await info...");
    17         } catch (InterruptedException e1) {
    18             e1.printStackTrace();
    19         } finally {
    20             lock.unlock();
    21         }
    22     }
    23     
    24     public void signal(){
    25         try {
    26             lock.lock();
    27             System.out.println("signal time is "+System.currentTimeMillis());
    28             condition.signal();
    29         } finally {
    30             lock.unlock();
    31         }
    32     }
    33 
    34     public void run() {
    35         await();
    36     }
    37 
    38 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         ReentrantLock lock = new ReentrantLock();
    10         Condition condition = lock.newCondition();
    11         MyService service = new MyService(lock,condition);
    12         new Thread(service).start();
    13         try {
    14             Thread.sleep(3000);
    15         } catch (InterruptedException e) {
    16             e.printStackTrace();
    17         }
    18         service.signal();
    19     }
    20 }
    await time is 1501142954379
    signal time is 1501142957381
    after await info...
    

     成功实现等待通知模式,整理一下,下表的方法功能是对应的

    Object

    Condition

    Wait()

    Await()

    Wait(long timeout)

    Await(long time,TimeUnit unit)

    Notify()

    Signal()

    notifyAll()

    signalAll()

    使用多个Condition实现通知部分线程

     1 public class MyService implements Runnable {
     2     
     3     protected ReentrantLock lock;
     4     protected Condition conditionA;
     5     protected Condition conditionB;
     6     
     7     public MyService(ReentrantLock lock,Condition conditionA,Condition conditionB){
     8         this.lock = lock;
     9         this.conditionA = conditionA;
    10         this.conditionB = conditionB;
    11     }
    12     
    13     public void await_A(){
    14         try {
    15             lock.lock();
    16             System.out.println(Thread.currentThread().getName()+" await_A time is "+System.currentTimeMillis());
    17             conditionA.await();
    18             System.out.println(Thread.currentThread().getName()+" after await_A info...");
    19         } catch (InterruptedException e1) {
    20             e1.printStackTrace();
    21         } finally {
    22             lock.unlock();
    23         }
    24     }
    25     
    26     public void await_B(){
    27         try {
    28             lock.lock();
    29             System.out.println(Thread.currentThread().getName()+" await_B time is "+System.currentTimeMillis());
    30             conditionB.await();
    31             System.out.println(Thread.currentThread().getName()+" after_B await info...");
    32         } catch (InterruptedException e1) {
    33             e1.printStackTrace();
    34         } finally {
    35             lock.unlock();
    36         }
    37     }
    38     
    39     public void signal_A(){
    40         try {
    41             lock.lock();
    42             System.out.println(Thread.currentThread().getName()+" signal_A time is "+System.currentTimeMillis());
    43             conditionA.signal();
    44         } finally {
    45             lock.unlock();
    46         }
    47     }
    48 
    49     public void signal_B(){
    50         try {
    51             lock.lock();
    52             System.out.println(Thread.currentThread().getName()+" signal_B time is "+System.currentTimeMillis());
    53             conditionB.signal();
    54         } finally {
    55             lock.unlock();
    56         }
    57     }
    58     
    59     public void run() {
    60         String tname = Thread.currentThread().getName();
    61         if (tname.equals("A")) {
    62             await_A();
    63         } else if (tname.equals("B")) {
    64             await_B();
    65         }
    66     }
    67 
    68 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         ReentrantLock lock = new ReentrantLock();
    10         
    11         Condition conditionA = lock.newCondition();
    12         Condition conditionB = lock.newCondition();
    13         MyService service = new MyService(lock,conditionA,conditionB);
    14         
    15         Thread tA = new Thread(service);
    16         tA.setName("A");
    17         tA.start();
    18         
    19         Thread tB = new Thread(service);
    20         tB.setName("B");
    21         tB.start();
    22         
    23         try {
    24             Thread.sleep(3000);
    25         } catch (InterruptedException e) {
    26             e.printStackTrace();
    27         }
    28         
    29         service.signal_A();
    30     }
    31 }
    A await_A time is 1501482321344
    B await_B time is 1501482321346
    main signal_A time is 1501482324344
    A after await_A info...
    

    可以看到只唤醒了A线程。。。

    一对一的生产者消费者  

     1 /**
     2  * 生产者和消费者一对一
     3  * @author ko
     4  *
     5  */
     6 public class MyService {
     7     
     8     protected ReentrantLock lock = new ReentrantLock();
     9     protected Condition condition = lock.newCondition();
    10     protected boolean hasValue = false;
    11     
    12     public void set(){
    13         try {
    14             lock.lock();
    15             while (hasValue == true) {
    16                 condition.await();
    17             }
    18             System.out.println("★");
    19             hasValue = true;
    20             condition.signal();
    21         } catch (InterruptedException e) {
    22             // TODO Auto-generated catch block
    23             e.printStackTrace();
    24         } finally {
    25             lock.unlock();
    26         }
    27     }
    28     
    29     public void get(){
    30         try {
    31             lock.lock();
    32             while (hasValue == false) {
    33                 condition.await();
    34             }
    35             System.out.println("☆");
    36             hasValue = false;
    37             condition.signal();
    38         } catch (InterruptedException e) {
    39             // TODO Auto-generated catch block
    40             e.printStackTrace();
    41         } finally {
    42             lock.unlock();
    43         }
    44     }
    45     
    46 }
     1 /**
     2  * 生产者
     3  * @author ko
     4  *
     5  */
     6 public class Producer implements Runnable {
     7 
     8     protected MyService myService;
     9     
    10     public Producer(MyService myService) {
    11         super();
    12         this.myService = myService;
    13     }
    14 
    15     public void run() {
    16         for (int i = 0; i < Integer.MAX_VALUE; i++) {
    17             myService.set();
    18         }
    19     }
    20 
    21 }
     1 /**
     2  * 消费者
     3  * @author ko
     4  *
     5  */
     6 public class Customer implements Runnable {
     7 
     8     protected MyService myService;
     9     
    10     public Customer(MyService myService) {
    11         super();
    12         this.myService = myService;
    13     }
    14 
    15     public void run() {
    16         for (int i = 0; i < Integer.MAX_VALUE; i++) {
    17             myService.get();
    18         }
    19     }
    20 
    21 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         MyService myService = new MyService();
    10         Producer p = new Producer(myService);
    11         Customer c = new Customer(myService);
    12         
    13         new Thread(p).start();
    14         new Thread(c).start();
    15         
    16     }
    17 }

    打印结果

    多对多的生产者消费者

     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7 
     8     public static void main(String[] args) {
     9         MyService myService = new MyService();
    10         
    11         for (int i = 0; i < 10; i++) {
    12             new Thread(new Producer(myService)).start();
    13             new Thread(new Customer(myService)).start();
    14         }
    15         
    16     }
    17 }
     1 /**
     2  * 生产者和消费者多对多
     3  * @author ko
     4  *
     5  */
     6 public class MyService {
     7     
     8     protected ReentrantLock lock = new ReentrantLock();
     9     protected Condition condition = lock.newCondition();
    10     protected boolean hasValue = false;
    11     
    12     public void set(){
    13         try {
    14             lock.lock();
    15             while (hasValue == true) {
    16                 System.out.println("有可能★连续打印");
    17                 condition.await();
    18             }
    19             System.out.println("★");
    20             hasValue = true;
    21             condition.signalAll();
    22         } catch (InterruptedException e) {
    23             // TODO Auto-generated catch block
    24             e.printStackTrace();
    25         } finally {
    26             lock.unlock();
    27         }
    28     }
    29     
    30     public void get(){
    31         try {
    32             lock.lock();
    33             while (hasValue == false) {
    34                 System.out.println("有可能☆连续打印");
    35                 condition.await();
    36             }
    37             System.out.println("☆");
    38             hasValue = false;
    39             condition.signalAll();
    40         } catch (InterruptedException e) {
    41             // TODO Auto-generated catch block
    42             e.printStackTrace();
    43         } finally {
    44             lock.unlock();
    45         }
    46     }
    47     
    48 }

    要注意的是由于现在是多个生产者消费者,所以condition.signal()要改为condition.signalAll(),其它代码不变。

    查看打印结果,发现★和☆总是间隔打印,但是 有可能★连续打印 和 有可能☆连续打印 却有可能连续打印,这是因为改为signalAll后唤醒的是所有线程,有可能再次把自己唤醒,所以会出现这种情况。

    公平锁与非公平锁

    公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,而非公平锁是一种抢占机制,随机的。

    还是上面的代码,给ReentrantLock换个有isFair参数的构造方法,new ReentrantLock(isFair) true就是公平锁,false就是非公平锁。再给打印的语句加上线程名,当为true时,线程是按顺序打印,为false时随机打印。

     方法getHoldCount()的使用

    getHoldCount()表示当前线程获取锁的个数

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     public void method1(){
     4         try {
     5             lock.lock();
     6             System.out.println(Thread.currentThread().getName()+"线程保持lock锁的个数:"+lock.getHoldCount()+" method1");
     7             method2();
     8         } catch (Exception e) {
     9             e.printStackTrace();
    10         } finally {
    11             lock.unlock();
    12         }
    13     }
    14     
    15     public void method2(){
    16         try {
    17             lock.lock();
    18             System.out.println(Thread.currentThread().getName()+"线程保持lock锁的个数:"+lock.getHoldCount()+" method2");
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         } finally {
    22             lock.unlock();
    23         }
    24     }
    25 }
     1 public class ThreadA extends Thread {
     2 
     3     protected MyService myService;
     4     
     5     public ThreadA(MyService myService) {
     6         super();
     7         this.myService = myService;
     8     }
     9 
    10     public void run() {
    11         myService.method1();
    12     }
    13 
    14 }
    1 public class Test {
    2     public static void main(String[] args) {
    3         MyService myService = new MyService();
    4         new ThreadA(myService).start();
    5     }
    6 }

    getQueueLength()方法使用

    getQueueLength()表示等待获取lock锁的估计线程个数。

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock();
     3     
     4     public void getql(){
     5         System.out.println("等待获取lock锁的估计线程个数:"+lock.getQueueLength()+" method1");
     6     }
     7 
     8     public void synmethod(){
     9         System.out.println(Thread.currentThread().getName()+"开始了。。。");
    10         lock.lock();
    11         try {
    12             Thread.sleep(5000);
    13         } catch (InterruptedException e) {
    14             e.printStackTrace();
    15         }
    16         lock.unlock();
    17     }
    18 }
     1 public class ThreadA extends Thread {
     2     protected MyService myService;
     3     
     4     public ThreadA(MyService myService) {
     5         super();
     6         this.myService = myService;
     7     }
     8 
     9     public void run() {
    10         myService.synmethod();
    11     }
    12 }
     1 public class Test {
     2     public static void main(String[] args) {
     3         MyService myService = new MyService();
     4         new ThreadA(myService).start();
     5         new ThreadA(myService).start();
     6         new ThreadA(myService).start();
     7         new ThreadA(myService).start();
     8         new ThreadA(myService).start();
     9         while (true) {
    10             myService.getql();
    11             try {
    12                 Thread.sleep(900);
    13             } catch (InterruptedException e) {
    14                 e.printStackTrace();
    15             }
    16         }
    17     }
    18 }

    getWaitQueueLength(condition)的用法

     getWaitQueueLength(condition) 表示返回等待与此锁相关的给定条件condition的线程估计数。比如有3个线程都执行了同一个condition的await方法,那么调用getWaitQueueLength(condition)返回的就是3.

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock();
     3     protected Condition condition = lock.newCondition();
     4     protected Condition condition1 = lock.newCondition();
     5     
     6 
     7     public void synmethod(){
     8         System.out.println(Thread.currentThread().getName()+"开始了。。。");
     9         lock.lock();
    10         System.out.println("进入lock锁与condition关联的的估计线程个数:"+lock.getWaitQueueLength(condition));
    11         System.out.println("进入lock锁与condition1关联的的估计线程个数:"+lock.getWaitQueueLength(condition1));
    12         System.out.println("");
    13         try {
    14             if (!Thread.currentThread().getName().contains("2")) {
    15                 condition.await();
    16             }else{
    17                 condition1.await();
    18             }
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         lock.unlock();
    23     }
    24 }
     1 public class Test {
     2     public static void main(String[] args) {
     3         MyService myService = new MyService();
     4         new ThreadA(myService).start();
     5         new ThreadA(myService).start();
     6         new ThreadA(myService).start();
     7         new ThreadA(myService).start();
     8         new ThreadA(myService).start();
     9     }
    10 }

    hasQueuedThread(thread)和hasQueuedThreads()的使用

     hasQueuedThread(thread)返回的是线程thread是否在等待获取lock锁

    hasQueuedThreads()返回的是是否有线程正在等待获取lock锁

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock();
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void hasa(Thread thread){
     6         if (lock.hasQueuedThread(thread)) {
     7             System.out.println(thread.getName()+"正在等待获取lock锁。。。");
     8         }else{
     9             System.out.println(thread.getName()+"不在等待获取lock锁。。。");
    10         }
    11         System.out.println("是否有线程在等待获取lock锁:"+lock.hasQueuedThreads());
    12         System.out.println("");
    13     }
    14 
    15     public void synmethod(){
    16         System.out.println(Thread.currentThread().getName()+"开始了。。。");
    17         lock.lock();
    18         
    19         if (Thread.currentThread().getName().contains("1")) {
    20             try {
    21                 condition.await();
    22             } catch (InterruptedException e) {
    23                 e.printStackTrace();
    24             }
    25         }
    26         try {
    27             Thread.sleep(15000);
    28         } catch (InterruptedException e) {
    29             // TODO Auto-generated catch block
    30             e.printStackTrace();
    31         }
    32         lock.unlock();
    33     }
    34 }
     1 public class Test {
     2     public static void main(String[] args) {
     3         MyService myService = new MyService();
     4         ThreadA ta = new ThreadA(myService);
     5         ta.start();
     6         ThreadA tb = new ThreadA(myService);
     7         tb.start();
     8         while (true) {
     9             myService.hasa(ta);
    10             myService.hasa(tb);
    11             System.out.println(""+ta.getName());
    12             try {
    13                 Thread.sleep(1000);
    14             } catch (InterruptedException e) {
    15                 e.printStackTrace();
    16             }
    17         }
    18     }
    19 }

    hasWaiters(condition)的用法

    hasWaiters(condition)表示是否有线程进入了lock锁与condition相关联的等待中。

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock();
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         System.out.println(Thread.currentThread().getName()+"开始了。。。");
     7         lock.lock();
     8         
     9         System.out.println("是否有线程进入了lock锁与condition相关联的等待中:"+lock.hasWaiters(condition));
    10         if (Thread.currentThread().getName().contains("0")) {
    11             try {
    12                 condition.await();
    13             } catch (InterruptedException e) {
    14                 e.printStackTrace();
    15             }
    16         }
    17         try {
    18             Thread.sleep(3000);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         lock.unlock();
    23     }
    24 }
     1 public class Test {
     2     public static void main(String[] args) {
     3         MyService myService = new MyService();
     4         
     5         ThreadA ta = new ThreadA(myService);
     6         ta.start();
     7         
     8         try {
     9             Thread.sleep(3500);
    10         } catch (InterruptedException e) {
    11             e.printStackTrace();
    12         }
    13         
    14         ThreadA tb = new ThreadA(myService);
    15         tb.start();
    16         
    17     }
    18 }

    方法isFair()、isHeldByCurrentThread()、isLocked()的使用

    isFair()判断线程锁是不是公平锁

    isHeldByCurrentThread()查询当前线程是否保持此锁定

    isLocked()查询此锁定是否由任意线程保持

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         System.out.println("lock锁是不是公平锁:"+lock.isFair());
     7         System.out.println("lock锁定是否由任意线程保持:"+lock.isLocked());
     8         System.out.println(Thread.currentThread().getName()+"是否保持lock锁定:"+lock.isHeldByCurrentThread());
     9         lock.lock();
    10         System.out.println("lock锁定是否由任意线程保持:"+lock.isLocked());
    11         System.out.println(Thread.currentThread().getName()+"是否保持lock锁定:"+lock.isHeldByCurrentThread());
    12         lock.unlock();
    13     }
    14 }
    1 public class Test {
    2     public static void main(String[] args) {
    3         MyService myService = new MyService();
    4         
    5         ThreadA ta = new ThreadA(myService);
    6         ta.start();
    7     }
    8 }

     

    lockInterruptibly()方法的使用

    lockInterruptibly()比lock()获取锁之前多了个判断,如果当前线程未被中断,则获取锁定,如果已被中断,则抛出java.lang.InterruptedException异常。

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         try {
     7             System.out.println(Thread.currentThread().getName()+" begin "+new Date().toString());
     8             for (int i = 0; i < Integer.MAX_VALUE/20; i++) {// 大概会延长7 8s,这里不用sleep延长线程时间,而是这样写,是因为调用线程的interrupt()方法时,如果线程在sleep会报异常
     9                 Math.random();
    10             }
    11             if(new Random().nextInt(5)%2==0){// 随机
    12                 System.out.println(Thread.currentThread().getName()+" 使用的是lock() ");
    13                 lock.lock();
    14             }else{
    15                 System.out.println(Thread.currentThread().getName()+" 使用的是lockInterruptibly() ");
    16                 lock.lockInterruptibly();
    17             }
    18             
    19             System.out.println(Thread.currentThread().getName()+" lock 1 "+new Date().toString());
    20             for (int i = 0; i < Integer.MAX_VALUE/20; i++) {// 同上
    21                 Math.random();
    22             }
    23         } catch (InterruptedException e) {
    24             // TODO Auto-generated catch block
    25             e.printStackTrace();
    26         } finally {
    27             System.out.println(Thread.currentThread().getName()+" lock 2 "+new Date().toString());
    28             if (lock.isHeldByCurrentThread()) {
    29                 lock.unlock();
    30             }
    31             System.out.println(Thread.currentThread().getName()+" end "+new Date().toString());
    32         }
    33     }
    34 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         MyService myService = new MyService();
     9         
    10         ThreadA taa = new ThreadA(myService);
    11         taa.setName("taa");
    12         taa.start();
    13         
    14         try {
    15             Thread.sleep(1500);// 等前面的线程都启动好
    16         } catch (InterruptedException e) {
    17             e.printStackTrace();
    18         }
    19         
    20         System.out.println("taa interrupt "+new Date().toString());
    21         taa.interrupt();// 打标记  这个时候taa还没有进入lock锁里
    22         
    23     }
    24 }

    代码里采用了随机的处理,有的时候使用的是lock(),有的时候使用的是lockInterruptibly(),多运行几遍就能得到两种结果。

     lock.tryLock()、lock.tryLock(timeout, unit)方法使用

    lock.tryLock())  立即返回,获得锁返回true,没获得锁返回false

    lock.tryLock(3, TimeUnit.SECONDS) 等待3s,3s后,获得锁返回true,没获得锁返回false

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         try {
     7             System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString());
     8             
     9             if (lock.tryLock()) {// 立即返回,获得锁返回true,没获得锁返回false
    10                 System.out.println(Thread.currentThread().getName()+"获得锁");
    11             } else {
    12                 System.out.println(Thread.currentThread().getName()+"没有获得锁");
    13             }
    14             
    15 //            if (lock.tryLock(3, TimeUnit.SECONDS)) {// 等待3s,3s后,获得锁返回true,没获得锁返回false
    16 //                System.out.println(Thread.currentThread().getName()+"获得锁的时间"+new Date().toString());
    17 //                Thread.sleep(10000);
    18 //            } else {
    19 //                System.out.println(Thread.currentThread().getName()+"没有获得锁");
    20 //            }
    21             
    22             System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
    23         } catch (Exception e) {
    24             e.printStackTrace();
    25         }
    26     }
    27 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         MyService myService = new MyService();
     9         
    10         ThreadA ta = new ThreadA(myService);
    11         ta.setName("ta");
    12         ta.start();
    13         
    14         ThreadA taa = new ThreadA(myService);
    15         taa.setName("taa");
    16         taa.start();
    17     }
    18 }

    awaitUninterruptibly()方法使用

    当在线程等待的时候,如果外部要中断该线程,不会报InterruptedException异常,而await()会报异常

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         try {
     7             System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString());
     8 
     9             lock.lock();
    10             
    11             if (new Random().nextInt(5)%2 == 0) {
    12                 System.out.println(Thread.currentThread().getName()+"走的是await()");
    13                 condition.await();
    14             } else {
    15                 System.out.println(Thread.currentThread().getName()+"走的是awaitUninterruptibly()");
    16                 condition.awaitUninterruptibly();
    17             }
    18             
    19         } catch (Exception e) {
    20             e.printStackTrace();
    21         } finally {
    22             System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
    23             lock.unlock();
    24         }
    25     }
    26 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         MyService myService = new MyService();
     9         
    10         ThreadA taa = new ThreadA(myService);
    11         taa.setName("taa");
    12         taa.start();
    13         
    14         try {
    15             Thread.sleep(1000);
    16         } catch (InterruptedException e) {
    17             e.printStackTrace();
    18         }
    19         taa.interrupt();// 打标记
    20     }
    21 }

    awaitUntil(Time time)方法使用

    awaitUntil(Time time)和await()一样会使当前线程进入等待状态,不过它有个截止时间,到了time这个时间,自动唤醒。

     1 public class MyService {
     2     protected ReentrantLock lock = new ReentrantLock(true);
     3     protected Condition condition = lock.newCondition();
     4     
     5     public void synmethod(){
     6         try {
     7             System.out.println(Thread.currentThread().getName()+"进入方法"+new Date().toString());
     8 
     9             lock.lock();
    10             
    11             Calendar calendar = Calendar.getInstance();
    12             calendar.add(Calendar.SECOND, 10);
    13             System.out.println("begin awaitUntil "+new Date().toString());
    14             condition.awaitUntil(calendar.getTime());// 
    15             System.out.println("after awaitUntil "+new Date().toString());
    16 
    17         } catch (Exception e) {
    18             e.printStackTrace();
    19         } finally {
    20             System.out.println(Thread.currentThread().getName()+"方法结束"+new Date().toString());
    21             lock.unlock();
    22         }
    23     }
    24 }
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         MyService myService = new MyService();
     9         
    10         ThreadA taa = new ThreadA(myService);
    11         taa.setName("taa");
    12         taa.start();
    13     }
    14 }

     使用Condition实现顺序执行

     1 /**
     2  * 利用condition实现顺序执行
     3  * @author ko
     4  *
     5  */
     6 public class MyService implements Runnable{
     7     protected ReentrantLock lock;
     8     protected Condition signalCondition;// 在某个线程里负责等待
     9     protected Condition awaitCondition;// 在某个线程里负责唤醒
    10     
    11     public MyService(ReentrantLock lock, Condition signalCondition, Condition awaitCondition) {
    12         super();
    13         this.lock = lock;
    14         this.signalCondition = signalCondition;
    15         this.awaitCondition = awaitCondition;
    16     }
    17 
    18     public void print(Condition signalCondition, Condition awaitCondition) throws InterruptedException{
    19         lock.lock();
    20         for (int j = 0; j < 10; j++) {
    21             for (int i = 1; i < 4; i++) {
    22                 System.out.println(Thread.currentThread().getName()+" "+i);
    23             }
    24             System.out.println("");
    25             signalCondition.signal();
    26             awaitCondition.await();
    27         }
    28         lock.unlock();
    29     }
    30 
    31     public void run() {
    32         try {
    33             print(signalCondition, awaitCondition);
    34         } catch (InterruptedException e) {
    35             e.printStackTrace();
    36         }
    37     }
    38     
    39 }
    myservice
     1 /**
     2  * 测试类
     3  * @author ko
     4  *
     5  */
     6 public class Test {
     7     public static void main(String[] args) {
     8         ReentrantLock lock = new ReentrantLock();
     9         Condition conditionA = lock.newCondition();
    10         Condition conditionB = lock.newCondition();
    11         Condition conditionC = lock.newCondition();
    12         
    13         MyService myService = new MyService(lock, conditionB, conditionA);
    14         
    15         new Thread(new MyService(lock, conditionB, conditionA),"thread a").start();
    16         new Thread(new MyService(lock, conditionC, conditionB),"thread b").start();
    17         new Thread(new MyService(lock, conditionA, conditionC),"thread c").start();
    18 
    19     }
    20 }
    test
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    
    thread a 1
    thread a 2
    thread a 3
    
    thread b 1
    thread b 2
    thread b 3
    
    thread c 1
    thread c 2
    thread c 3
    打印结果
  • 相关阅读:
    使用C++为对象分配与释放内存时的几个好习惯
    OGRE渲染流程
    【问题解决记录】无法识别的标志“-sdlMode”,在“p2”中
    四元数 Quaternion
    《The Cg Tutorial》阅读笔记——凹凸贴图 Bump Mapping
    尝试优化骨骼动画计算的意外收获——使用嵌入式汇编对float转int进行优化
    Model 的 Meta 选项
    dns资料
    ansible中的变量
    DockerFile与docker-compose.yml是什么
  • 原文地址:https://www.cnblogs.com/shamo89/p/7245972.html
Copyright © 2020-2023  润新知