JUC之线程通信定制化(第三部分)

83 阅读1分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

之前文章中写了下Condition的使用,这里我们详细说下其中的用法:

首先使用Condition需要实例化Lock

 private Lock lock = new ReentrantLock();   //创建锁

使用lock里面的newCondition方法创建Condition对象:

 private Condition c1 = lock.newCondition();

其优点:比synchronized更安全、更高效。

选自:廖雪峰的官网-Java教程

Condition提供的await()signal()signalAll()原理和synchronized锁对象的wait()notify()notifyAll()是一致的,并且其行为也是一样的:

  • await()会释放当前锁,进入等待状态;
  • signal()会唤醒某个等待线程;
  • signalAll()会唤醒所有等待线程;
  • 唤醒线程从await()返回后需要重新获得锁。

需要注意的是伤处signal\signalAll与await方法的对应关系;

通过一个例子来理解线程间的定制化:

要求:

image-20211230213747403

实现代码:

 package com.JUC;
 ​
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 //线程间的定制化通信
 class ShareRewsource {
     private int flag = 1;  //1表示线程AAA,2表示线程BBB,3表示线程CCC
 ​
     private Lock lock = new ReentrantLock();   //创建锁
     //代替Object中的等待、唤醒等操作,更加的安全高效
     private Condition c1 = lock.newCondition();  //对标AAA线程
     private Condition c2 = lock.newCondition();  //对标BBB线程
     private Condition c3 = lock.newCondition();  //对标CC线程
 ​
     //创建方法
     public void print5(int loop) {
         lock.lock();
         try {
             while (flag != 1) {
                 c1.await();
             }
             //操作
             for (int i = 1; i <= 5; i++) {
                 System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
             }
             flag = 2;
             c2.signal();  //通知BBB线程  唤醒BBB线程,唤醒后在BBB线程的await后继续执行;
 ​
         } catch (InterruptedException e) {
             e.printStackTrace();
         } finally {
             lock.unlock();
         }
 ​
     }
 ​
     //创建方法
     public void print10(int loop) {
         lock.lock();
         try {
             while (flag != 2) {
                 c2.await();
             }
             //操作
             for (int i = 1; i <= 10; i++) {
                 System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
             }
             flag = 3;
             c3.signal();  //通知CCC线程
 ​
         } catch (InterruptedException e) {
             e.printStackTrace();
         } finally {
             lock.unlock();
         }
 ​
     }
 ​
     //创建方法
     public void print15(int loop) {
         lock.lock();
         try {
             while (flag != 3) {
                 c3.await();
             }
             //操作
             for (int i = 1; i <= 15; i++) {
                 System.out.println(Thread.currentThread().getName() + "-----" + i + "::" + loop);
             }
             flag = 1;
             c1.signal();  //通知AAA线程
 ​
         } catch (InterruptedException e) {
             e.printStackTrace();
         } finally {
             lock.unlock();
         }
 ​
     }
 ​
 }
 ​
 public class ThreadPrivateDemo {
     public static void main(String[] args) {
         ShareRewsource rewsource = new ShareRewsource();
         new Thread(() -> {
             for (int i = 1; i <= 10; i++) {
                 rewsource.print5(i);
             }
         }, "AAA").start();
         new Thread(() -> {
             for (int i = 1; i <= 10; i++) {
                 rewsource.print10(i);
             }
         }, "BBB").start();
         new Thread(() -> {
             for (int i = 1; i <= 10; i++) {
                 rewsource.print15(i);
             }
         }, "CCC").start();
     }
 }

其中对应关系:注意唤醒和等待所在的代码段

c2.signal() --> c2.await()

c3.signal() --> c3.await()

c1.signal() --> c1.await()