zoukankan      html  css  js  c++  java
  • Java多线程 — — lock、await 、signal 组合 替换 sync、wait、notifyAll,实现精准唤醒线程

    接上篇博客我们使用老旧的多线程API实现了线程间通信,

    但是为了让线程运行的更有效率,

    本篇我们采用 lock、await 、signal 新特性,

    进行再次酿造,

    旧瓶子,装点新酒

     


    需求:

    很简单,要求顺次打印1次A,2次B,3次C,循环来10遍。

    废话不多说,直接上源码:

    package ldk.test;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @Author: ldk
     * @Date: 2020/12/18 16:03
     * @Describe:
     */
    public class ThreadTest1 {
    
    
        public static void main(String[] args) {
            Data data = new Data();
            //生产者线程A
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    try {
                        data.print1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "A").start();
    
            //生产者线程B
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    try {
                        data.print2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "B").start();
    
            //消费者线程C
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    try {
                        data.print3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "C").start();
    
    
        }
    
    
        //数据类
        static class Data {
            //表示数据个数
            private int number = 1;
    
            private Lock lock = new ReentrantLock();
            private Condition condition1 = lock.newCondition();
            private Condition condition2 = lock.newCondition();
            private Condition condition3 = lock.newCondition();
    
            public void print1() throws InterruptedException {
                lock.lock();
                try {
                    while (number != 1) {
                        condition1.await();
                    }
                    System.out.println(Thread.currentThread().getName());
                    number = 2;
                    condition2.signal();
                } finally {
                    lock.unlock();
                }
    
            }
    
            public void print2() throws InterruptedException {
                lock.lock();
                try {
                    while (number != 2) {
                        condition2.await();
                    }
                    for (int i = 0; i < 2; i++) {
                        System.out.println(Thread.currentThread().getName());
                    }
                    number = 3;
                    condition3.signal();
                } finally {
                    lock.unlock();
                }
    
            }
    
            public void print3() throws InterruptedException {
                lock.lock();
                try {
                    while (number != 3) {
                        condition3.await();
                    }
                    for (int i = 0; i < 3; i++) {
                        System.out.println(Thread.currentThread().getName());
                    }
                    number = 1;
                    condition1.signal();
                } finally {
                    lock.unlock();
                }
    
            }
        }
    }

    执行结果:

     简单分析:

    需求很明了,
    按顺序走10遍,
    我们主要优化的是精准唤醒,
    每次执行完须定向地执行下个目标,
    lock和unlock想必大家很熟悉,就是上锁,解锁操作,

    主要是condition控制了线程的精准调度

    流程简单分析:
    
    1、值初始化为1,很自然进入print1,打印1次
    
    2、值变成2,唤醒condition2,执行打印2次,唤醒condition3(即使开始是condition3抢到,现在值为2,condition3线程只能等待,最终还是有condition2执行)
    
    3、此时值为3,且condition3唤醒,打印3次,值设置为1,唤醒condition1,
    
    4、...周而复始,打印10遍为止。
  • 相关阅读:
    218. The Skyline Problem (LeetCode)
    并发编程-读书笔记
    Lock Free (无锁并发)
    最近公共祖先 LCA 递归非递归
    Node.js 开发指南-读书笔记
    [paper reading] C-MIL: Continuation Multiple Instance Learning for Weakly Supervised Object Detection CVPR2019
    开发者必备,超实用的PHP代码片段!
    二级菜单联动效果
    页面js框架
    我的java mvc
  • 原文地址:https://www.cnblogs.com/dk1024/p/14164836.html
Copyright © 2011-2022 走看看