zoukankan      html  css  js  c++  java
  • 阿里一面感受【补面经】

    链接:https://www.nowcoder.com/discuss/113050
    阿里一面20min

    说项目,说平常怎么学习java,说除了项目有自己开发过什么。

    问基础

    分代回收算法

    对象分类

        这种算法并不是一种新的算法,而是根据对象的存活周期的不同而将内存分为几块,分别是新生代、老年代和永久代。

    新生代:朝生夕灭的对象(例如方法的局部变量等);

    老年代:存活的比较久但还是要死的对象(例如缓存对象、单例对象等);

    永久代:对象生成后几乎不灭的对象(例如加载过的类信息);

    内存区域

        新生代和老年代都在Java堆,永久代在方法区。

    Java对象的回收

        新生代:采用复制算法,新生对象一般存活率较低,因此可以不使用50%的内存空间作为空闲,一般的使用两块10%的内存。

        作为空闲和活动区间,而另外80%的内存则是用来给新建对象分配内存的。一旦发生GC,将10%的活动区间与另外80%中存活的对象转移到10%的空闲空间,接下来,将之前90%的内存全部释放。以此类推,如图所示:

    堆大小=新生代+老年代,新生代和老年代的比例为1:2,新生代细分为一块交大的Eden空间和两块较小的Survivor空间,分别被命名为from和to。

    老年代:老年代中使用标记-清除或者标记-整理算法进行垃圾回收,回收次数相对较少,每次回收时间比较长。

    方法区对象回收

        永久代指的是虚拟机内存中的方法区,永久代垃圾回收 比较少,效率也比较低,但也必须进行垃圾回收,否则永久代内存不够用时仍然会抛出OutOfMemoryError异常。永久代也使用标记-清除或标记-整理算法进行垃圾回收。

    对象如何进入老年代

    对象优先在新生代的eden区分配内存,但是也并不绝对,下面几种情况对象会晋升到老年代。

    1、大对象直接进入老年代。比如很长的字符串,或者很大的数组等。

    2、长期存活的对象进入老年代。在堆中分配内存的对象,其内存布局的对象头中包含了GC分代年龄标记信息。如果对象在eden区出生,那么它的GC分代年龄初始值为1,每熬过一次Minor GC而不被回收这个值会增加1岁。当他的年龄到达一定的数值时(jdk1.7默认是15),就会晋升到老年代。

    3、动态对象年龄判定。当Survivor空间中相同年龄所有对象的大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代,而不需要达到默认的分代年龄。

    新生代用的什么算法,老年代用的什么算法

    新生代用的是复制算法,老年代用的是标记-清除或标记整理算法。

    lock ,sychronized,volatile的区别

    sychronized与volatile关键字区别:

    1、volatle关键字解决的是变量在多个线程之间的可见性;而sychronized关键字解决的是多个线程之间访问共享资源的同步性。

    2、volatile只能用于修饰变量,而synchronized可以修饰方法以及代码块。(volatile是线程同步的轻量级实现,所以volatile性能比synchronized要好,并且随着JDK新版本的发布,synchronized关键字在执行上得到很大的提升,在开发中使用synchronized关键字的比率还是比较大。)

    3、多线程访问volatile不会发生阻塞,而synchronized会发生阻塞。

    4、volatile能保证变量在多个线程之间的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和 公有内存中的数据做同步。

    线程安全包含原子性和可见性两个方面。对于用volatile修饰的变量,JVM只是保证从主存加载到线程工作内存的值是最新的。一句话说明volatile的作用:实现变量在多个线程之间的可见性。

    synchronized与lock的区别

    1、lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现。

    2、synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而lock在发生异常时,如果没有主动通过unlock()去释放锁,则很可能造成死锁现象,因此使用lock时需要在finally块中释放锁。

    3、lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能响应中断。

    4、通过lock可以知道有没有成功获取锁,而synchronized却无法办到。

    5、lock可以提高多个线程进行读操作的效率(读写锁)。

        在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

    乐观锁,悲观锁

    悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其他线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁、表锁等,读锁写锁等,都是在操作之前先上锁。Java中synchronized和ReetrantLock等独占锁就是悲观锁思想的实现。

    乐观锁:总是假设好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

    乐观锁使用场景,使用乐观锁的产品或中间件

    https://blog.csdn.net/strawqqhat/article/details/88743519

    线程池参数

    https://blog.csdn.net/strawqqhat/article/details/88748702

    一个核心池为2,等待队列3,最大线程数10的线程池,已有两个线程运行任务,第三个任务进来时如何处理

    判断等待队列中是否有地方存放该任务,如果有就将任务保存在等待队列中等待执行,没有就去判断最大可容纳的线程数,如果没有超出这个数量就去开创非核心线程执行任务,否则调用handler实现拒绝策略。

    缓存线程池的参数如何设置,特性是什么

    https://blog.csdn.net/strawqqhat/article/details/88749714

    什么是数据库事务

    数据库事务的性质,隔离级别

    https://blog.csdn.net/strawqqhat/article/details/88564150

    数据库如何实现串行化

    可重复读实现了读取前后数据内容一致,

    但是产生了数据条目不一致(幻读),

    可串行化解决了这个问题,

    串行化是最严格的事物隔离级别:

    事物a 执行读写操作时,会锁定检索的数据行范围(范围锁),这种锁会阻止其他事物在本范围内的一切操作,

    只有事物a执行完毕,提交事物后,才会释放范围锁,这样就避免了幻读。

    但是,实际项目中,这个级别的隔离很少用,因为并发性能低,容易死锁。
     

    缓存数据处理【说的LRU】

    https://blog.csdn.net/bie_niu1992/article/details/77750220

    场景题 关于redis的

    分布式锁,如何添加,放在什么位置

  • 相关阅读:
    00072_System类
    eWebEditor实现word图片自动转存
    wangEditor实现word图片自动转存
    xhEditor实现word图片自动转存
    TinyMCE实现word图片自动转存
    FCKEditor实现word图片自动转存
    CKEditor实现word图片自动转存
    Nginx大文件(百M以上)的上传下载实现技术
    百度WebUploader大文件(百M以上)的上传下载实现技术
    SpringCloud大文件(百M以上)的上传下载实现技术
  • 原文地址:https://www.cnblogs.com/strawqqhat/p/10602186.html
Copyright © 2011-2022 走看看