zoukankan      html  css  js  c++  java
  • JUC之线程间定制化通信

    线程通信之定制化

    之前文章中写了下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()

  • 相关阅读:
    【販売管理】「クレジットメモとデビットメモ」
    COALESCE [NULL でない最初の式を返す」
    【EXCEL】CONCAT(複数の文字列の連結)
    文字列内の検索 FIND
    テーブルコントロールTable Controls: スクロールを伴う場合の例
    SAP ABAP プログラム 選択画面定義 基本命令
    【転載】表示レイアウト実装方法
    php在linux中执行外部命令
    openldap+php-ldap操作
    MAC Ruby版本需要升级至2.2.2以上
  • 原文地址:https://www.cnblogs.com/xbhog/p/15756158.html
Copyright © 2011-2022 走看看