zoukankan      html  css  js  c++  java
  • ARTS第十一周

    ARTS第十一周

    ARTS是什么?

    Algorithm:每周至少做一个leetcode的算法题;
    Review:阅读并点评至少一篇英文技术文章;
    Tip/Techni:学习至少一个技术技巧;
    Share:分享一篇有观点和思考的技术文章。

    Algorithm

    题目:232. Implement Queue using Stacks

    解题思路

    题目要求用栈实现队列的功能。对比栈和队列的特性差异:栈的特性是先进后出,队列是先进先出。我们要用先进后出的容器实现先进先出的效果,考虑使用两个先进后出的容器来实现这种效果,相当于负负得正的效果。

    代码

    class MyQueue {
     //输入栈
        Stack<Integer> input;
        //输出栈
        Stack<Integer> output;
        /** Initialize your data structure here. */
        public MyQueue() {
            input = new Stack();
            output = new Stack();
        }
        
        /** Push element x to the back of queue. */
        public void push(int x) {
            input.push(x);
        }
        
        /** Removes the element from in front of queue and returns that element. */
        public int pop() {
            if (output.empty()) {
                while (!input.empty()) {
                    output.push(input.pop());
                }
            }
            return output.pop();
        }
        
        /** Get the front element. */
        public int peek() {
              if (output.empty()) {
                while (!input.empty()) {
                    output.push(input.pop());
                }
            }
            return output.peek();
        }
        
        /** Returns whether the queue is empty. */
        public boolean empty() {
            return input.empty() && output.empty();
        }
    }
    

    Review

    信号量Semaphore

    计数信号量,概念上讲,一个信号量保持了一组许可。每个acquire方法都会阻塞直到拿到一个许可。每个release方法增加一个许可,可能会释放一个阻塞的acquirer.然而,没有实际的许可对象,Semaphore只是保持一个可用的计数并采取相应的行为。

    信号量经常被用来限制线程数,而不是访问某些资源。比如下面的类,用了一个信号量控制访问池.

    class Pool {
       private static final int MAX_AVAILABLE = 100;
       private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
    
       public Object getItem() throws InterruptedException {
         available.acquire();
         return getNextAvailableItem();
       }
    
       public void putItem(Object x) {
         if (markAsUnused(x))
           available.release();
       }
    
       // Not a particularly efficient data structure; just for demo
    
       protected Object[] items = ... whatever kinds of items being managed
       protected boolean[] used = new boolean[MAX_AVAILABLE];
    
       protected synchronized Object getNextAvailableItem() {
         for (int i = 0; i < MAX_AVAILABLE; ++i) {
           if (!used[i]) {
              used[i] = true;
              return items[i];
           }
         }
         return null; // not reached
       }
    
       protected synchronized boolean markAsUnused(Object item) {
         for (int i = 0; i < MAX_AVAILABLE; ++i) {
           if (item == items[i]) {
              if (used[i]) {
                used[i] = false;
                return true;
              } else
                return false;
           }
         }
         return false;
       }
     }
    

    在获取一项信号量之前每个线程必须从信号量获得许可,保证有一项可用的信号量。当线程用完这项信号量,许可将返回给信号量,允许另一个线程去获得这项信号量。注意,调用acquire方法的时候不会保持同步锁定,因为这会阻止信号量返回池中。信号量封装了限制访问池所需的同步,与维护池本身一致性所需的任何同步分开。

    信号量初始化为1,并且使用它至多只有一个许可,能被用来做互斥锁。这通常被称为二进制信号量,因为它只有两种状态:1个可用的许可;0个可用的许可。当用这种方式,这个二进制信号量有一个属性:锁能被非拥有者释放,这能被用在一些特殊场景,比如死锁恢复。

    这个类的构造函数可用接受一个fairness参数。当设置为false的时候,此类不保证线程获得许可的顺序。事实上,允许barging意味着,调用acquire方法的线程能先于已经在等待的线程被分配到一个许可,逻辑上,这个新线程排到等待线程队列的开头。当fairness设置成true,信号量保证调用acquire方法的线程按照他们的调用顺序获得许可。注意,FIFO顺序一定适用于这些方法的特定内部执行点。所以,一个线程可以在另一个线程之前调用acquire方法,但是在另一个线程之后到达排序点,并且从方法返回时类似。另外注意,不定时的tryAcquire方法不遵守公平性设置,但会接受任何可用的许可。

    一般来说,信号量用来控制资源访问的时候应该被初始化为fair,为了确保访问某个资源的时候没有线程会饿死。当信号量用于其他类型的并发控制,非公平锁的吞吐量优势往往超过公平考量。

    Tip/Techni

    volatile关键字

    作用:在多线程环境下,保证了共享变量的“可见性”。

    原理:

    1.将当前处理器缓存行数据写回到系统内存。

    2.使其他cpu缓存了该内存地址的数据失效。

    synchronized

    作用:为修饰的对象加上锁,实现同步效果。

    修饰对象:

    1.普通同步方法:锁的是当前实例对象。

    2.静态同步方法:锁的是当前类的class对象。

    3.同步方法块:锁的是Synchronized括号里配置的对象。

    原理:基于进入和退出monitor对象来实现方法同步和代码块同步。

    Share

    最近一周主要在学习java高并发,也找了一堆资料,在此分享关于一篇java高并发学习路线的文章Java并发编程学习路线,作者根据自己学习java高并发的经历总结了一条学习路线,我看完之后感觉学习体验和我类似,文中提到的基本书都是学习java高并发比较经典的,推荐阅读,还有更重要的是,阅读的时候一定要把握书的脉络,这个个人感觉非常重要,否则学到的都是一个个的点,不成体系,很容易遗忘。另一点就是光看书是不够的,还要配合实践才能理解的深,目前我也还在学习这块知识中,共勉。

    如果您觉得本文对你有用,不妨帮忙点个赞,或者在评论里留言交流,欢迎您持续关注我的博客^_^
  • 相关阅读:
    纪中集训 Day 2
    纪中集训 Day1
    纪中集训 Day 0?
    BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster(模拟)
    BZOJ 3527: [Zjoi2014]力(FFT)
    wikioi 3132 高精度乘法(FFT)
    BZOJ 1085: [SCOI2005]骑士精神(A*算法)
    BZOJ 1009 :[HNOI2008]GT考试(KPM算法+dp+矩阵快速幂)
    BZOJ 1019 :[SHOI2008]汉诺塔(递推)
    BZOJ 1021 :[SHOI2008]Debt 循环的债务 (DP)
  • 原文地址:https://www.cnblogs.com/muxuanchan/p/10457998.html
Copyright © 2011-2022 走看看