zoukankan      html  css  js  c++  java
  • 第四章:(1)线程间定制化通信

    一、线程间定制化通信

      多个线程之间的执行时机并不是固定的,是由 CPU 来操作调度的,如果要让线程按照我们需要的顺序执行,这就是线程间定制化通信。

      

    二、案例

    1、题目要求

      三个线程之间按顺序调用,实现 A -> B -> C
      三个线程启动,要求如下:
      AA打印5次,BB打印10次,CC打印15次
      接着
      AA 打印5次,BB打印10次,CC打印15次
      ……进行10轮
     

    2、思考:

      (1)有顺序通知,需要有标识位;
      (2)有一个锁 Lock,3把钥匙 Condition;
      (3)判断标识位;
      (4)输出线程名 + 第几次 + 第几轮;
      (5)修改标志位,通知下一个;
      

    3、代码实现

    //第一步:创建资源类
    class ShareResource {
        //定义标志位
        // 1 AA     2 BB     3 CC
        private int flag = 1;
    
        //创建Lock锁
        private Lock lock = new ReentrantLock();
    
        //创建三个 Condition
        private Condition c1 = lock.newCondition();
        private Condition c2 = lock.newCondition();
        private Condition c3 = lock.newCondition();
    
        //打印5次,参数第几轮
        public void print5(int loop) throws InterruptedException {
            //上锁
            lock.lock();
    
            try {
                //第二步:判断    干活  通知
    
                //判断:防止虚假唤醒,使用 while 循环
                while (flag != 1) {
                    c1.await();
                }
    
                //干活
                for (int i = 1; i <= 5; i++) {
                    System.out.println(Thread.currentThread().getName()+" :: "+i+" :轮数:"+loop);
                }
    
                //通知
                flag = 2;     //修改标志位 2
                c2.signal();  //通知 BB 线程,唤醒 c2 等待的线程
    
            } finally {
                //解锁
                lock.unlock();
            }
        }
    
        //打印10次,参数第几轮
        public void print10(int loop) throws InterruptedException {
            //上锁
            lock.lock();
    
            try {
                //第二步:判断    干活  通知
    
                //判断:防止虚假唤醒,使用 while 循环
                while (flag != 2) {
                    c2.await();
                }
    
                //干活
                for (int i = 1; i <= 10; i++) {
                    System.out.println(Thread.currentThread().getName()+" :: "+i+" :轮数:"+loop);
                }
    
                //通知
                flag = 3;     //修改标志位 3
                c3.signal();  //通知 CC 线程,唤醒 c3 等待的线程
    
            } finally {
                //解锁
                lock.unlock();
            }
        }
    
        //打印15次,参数第几轮
        public void print15(int loop) throws InterruptedException {
            //上锁
            lock.lock();
    
            try {
                //第二步:判断    干活  通知
    
                //判断:防止虚假唤醒,使用 while 循环
                while (flag != 3) {
                    c3.await();
                }
    
                //干活
                for (int i = 1; i <= 15; i++) {
                    System.out.println(Thread.currentThread().getName()+" :: "+i+" :轮数:"+loop);
                }
    
                //通知
                flag = 1;     //修改标志位 1
                c1.signal();  //通知 AA 线程,唤醒 c1 等待的线程
    
            } finally {
                //解锁
                lock.unlock();
            }
        }
    }
    
    public class ThreadDemo3 {
    
        public static void main(String[] args) {
            ShareResource shareResource = new ShareResource();
    
            //创建多个线程,调用资源类的操作方法
            new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    try {
                        shareResource.print5(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "AA").start();
    
            new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    try {
                        shareResource.print10(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "BB").start();
    
            new Thread(() -> {
                for (int i = 1; i <= 10; i++) {
                    try {
                        shareResource.print15(i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "CC").start();
        }
    }

    三、多线程编程步骤

      第一步:创建资源类,在资源类创建数据和操作方法;

      第二步:在资源类操作方法
      (1)判断
      (2)干活
      (3)通知

      第三步:创建多个线程,调用资源类的操作方法;

      第四步:注意标志位的修改和定位;

  • 相关阅读:
    CentOS7 安装 Mysql 服务
    git 第一次 push 遇到问题
    为什么PHP(CLI)同一个错误信息会打印两次?
    python密码输入模块getpass
    Linux安装JDK详细步骤
    嘿嘿嘿,开始自学mysql
    Bable实现由ES6转译为ES5
    AJAX
    模板层
    lshw查看系统硬件信息
  • 原文地址:https://www.cnblogs.com/niujifei/p/15824325.html
Copyright © 2011-2022 走看看