• condition精准控制


    Lock版的生产者消费者问题

    那么在synchronized中呢,我们是使用wait和notify来控制线程的。

    public synchronized void increment() throws InterruptedException {
           while (number != 0) {
                // 等待
                this.wait();
    
            }
            Thread.sleep(100);
            number++; // 业务
            System.out.println(Thread.currentThread().getName() + " => " + number);
            // 通知其它线程我+1加完了
            this.notifyAll();
    
        }

    用了Lock之后、会有一些细微的改变,wait->condition.await, notify->condition.signal

    class doSomething {
    
        private int number = 0;
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
    
        // +1
        public void increse() throws InterruptedException {
            lock.lock();
            try {
    
                while (number != 0) {
                    condition.await();
    
                }
                Thread.sleep(100);
                number++;
                System.out.println(Thread.currentThread().getName() + "->" + number);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
    
                lock.unlock();
            }
    
        }
    
    
        // -1
        public void decrese() throws InterruptedException {
    
            lock.lock();
            try {
                while (number == 0) {
                    condition.await();
                }
                Thread.sleep(100);
                number--;
                System.out.println(Thread.currentThread().getName() + "->" + number);
                condition.signalAll();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
    
    }

    思考:既然有了wait和notify、那为什么我们还要多此一举来使用condition的等待和唤醒呢?

      这是因为condition能够做到有序,精准的通知和唤醒线程

    那么如何做到有序精准的来唤醒线程呢?

    public class C {
        public static void main(String[] args) {
            doSomething2 doSomething2 = new doSomething2();
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    doSomething2.printA();
    
                }
            }, "A").start();
    
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    doSomething2.printB();
    
                }
    
            }, "B").start();
    
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    doSomething2.printC();
    
                }
    
            }, "C").start();
    
        }
    }
    
    @SuppressWarnings("all")
    class doSomething2 {
    
        private int number = 1;
        Lock lock = new ReentrantLock();
        private Condition condition1 = lock.newCondition();
        private Condition condition2 = lock.newCondition();
        private Condition condition3 = lock.newCondition();
    
        public void printA() {
            lock.lock();
            try {
                while (number != 1) {
                    // 等待
                    condition1.await();
                }
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName() + "AAA");
                // 唤醒
                condition2.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void printB() {
            lock.lock();
            try {
                while (number != 1) {
                    // 等待
                    condition2.await();
                }
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName() + "BBB");
                // 唤醒
                condition3.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void printC() {
            lock.lock();
            try {
                while (number != 1) {
                    // 等待
                    condition3.await();
                }
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName() + "CCC");
                // 唤醒
                condition1.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
    }
    
    
  • 相关阅读:
    新添61工程文件后无法编译问题
    beaglebone_black_学习笔记——(4)闪烁LED之shell命令
    PADS技巧——铺铜
    自定义map对象,用于再不支持es6的map的时候
    vue.js基础学习(2)
    vue.js基础学习(1)
    ie浏览器float兼容性
    webAPI路由的使用
    webAPI中使用log4net进行日志记录
    webAPI中使用FormsAuthenticationTicket作为登录权限票据
  • 原文地址:https://www.cnblogs.com/YXBLOGXYY/p/14860873.html
Copyright © 2020-2023  润新知