• wait()、notify()、notifyAll()方法的理解


    wait()表示把线程挂起,挂起的时候会自动释放锁。

    notify() 随机的选择一个在指定对象上挂起的线程激活。

    notifyAll() 激活指定对象上挂起的所有线程

    条件队列:一组等待线程集合,能够通过某种方式来等待对应的条件为真。条件队列中的元素是一个正在等待相关条件的线程。

        通过条件队列构建高可响应的状态依赖类,条件等待存在三元关系 加锁、wait、一个条件谓词(包含多个状态变量) ,状态变量由一个锁保护

         在测试条件谓语之前必须先获得对象的锁。锁对象和条件队列对象(即调用wait()和notify()方法的对象)必须是同一个对象。

    如下实现自定义有界缓存实现

         基类代码

    package com.lifeStudy.algorith;
    
    public abstract class BaseBoundedBuffer<V> {
    
        private final V[] buf;
        private int tail;
        private int head;
        private int count;
    
        protected BaseBoundedBuffer(int capacity) {
            //还可以通过直接new Object[]数组,等到需要具体化时候才 强制转换单个元素
            buf = (V[]) new Object[capacity];//泛型擦除,其实就是(Object[])转换
        }
    
    
        protected synchronized final void doPut(V v) {
            buf[tail] = v;
            if (++tail == buf.length) {
                tail = 0;
            }
            count++;
        }
    
        protected synchronized final V doTake() {
            V rs = buf[head];
            buf[head] = null;
            if (++head == buf.length) {
                head = 0;
            }
            count--;
            return rs;
        }
    
    //下面是两个状态变量,队列是否满;队列是否为空 通过内置锁对象this
    public synchronized final boolean isFull() { return count == buf.length; } public synchronized final boolean isEmpty() { return count == 0; } }

    通过wait()实现条件队列

    package com.lifeStudy.algorith;
    
    
    public class BoundedBuffer<V> extends BaseBoundedBuffer<V> {//条件队列
    
        protected BoundedBuffer(int capacity) {
            super(capacity);
        }
    
        public synchronized void put(V v) throws InterruptedException {
    
            while (isFull()) {
                System.out.println(Thread.currentThread().getId() + " put竞争失败,挂起");
                this.wait();
                System.out.println(Thread.currentThread().getId() + " put被唤醒,二次激活");
            }
            doPut(v);
            this.notifyAll();//唤醒所有在this对象上挂起的线程
        }
    
        public synchronized V take() throws InterruptedException {
            while (isEmpty()) {
                System.out.println(Thread.currentThread().getId() + " get竞争失败,挂起");
                this.wait();//线程挂起,放开锁synchronized中this对象。
                System.out.println(Thread.currentThread().getId() + " get被唤醒,二次激活");
            }
            V v = doTake();
            this.notifyAll();//唤醒所有在this对象上挂起的线程
            return v;
        }
    
        public static void main(String... args) throws InterruptedException {
    
            BoundedBuffer<Integer> integerBoundedBuffer = new BoundedBuffer<Integer>(12);
    //        new Thread(new Consummer(integerBoundedBuffer)).start();
    //        TimeUnit.SECONDS.sleep(10);
            new Thread(new Producer(integerBoundedBuffer)).start();
            //通过下面可以看到  调用wait挂起线程时会释放锁.
    //        new Thread(new Producer(integerBoundedBuffer)).start();
    
    
    
        }
    
        private static class Consummer implements Runnable {
    
            private final BoundedBuffer bf;
    
            public Consummer(BoundedBuffer bf) {
                this.bf = bf;
            }
    
            public void run() {
                try {
                    while (true) {
                        bf.take();
                        System.out.println("get");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    
    
        private static class Producer implements Runnable {
            private final BoundedBuffer bs;
    
            protected Producer(BoundedBuffer bs) {
                this.bs = bs;
            }
    
            public void run() {
                try {
                    while (true) {
                        bs.put(123);
                        System.out.println("put");
                    }
    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    
    }
  • 相关阅读:
    Mysql如何进行分组,并且让每一组的结果按照某个字段排序,并且获取每一组的第一个字段
    Mysql报错:Packet for query is too large (1121604 > 1048576).You can change this value on the server by setting the max_allowed_packet variable
    JavaScript判断对象有没有定义
    本地设置VirtualBox虚拟机
    Mysql关于时间排序的问题
    PHP实现页面静态化
    301重定向的两种实现方法
    判断浏览器类型
    javascript DOM事件总结
    装饰器模式
  • 原文地址:https://www.cnblogs.com/09120912zhang/p/8617681.html
Copyright © 2020-2023  润新知