美文网首页
Java相关

Java相关

作者: Entry_1 | 来源:发表于2018-03-09 18:16 被阅读0次
    1. Java容器底层原理
    2. Java高并发内容
    3. JVM

    一. 容器底层原理

    1. ArrayList
      由数组实现,初始化数组长度,每次增加都会变成之前的1.5倍(扩容)。
      是线程不安全的,会产生fail-fast保护
      fail-fast机制?当方法检测到对象的并发修改,但是不允许这种修改时就会抛出ConcurrentModifictionException异常。

    2.Vector
    由数组实现,指定扩容或者*2
    线程安全,也有fail-fast保护,每一个操作都有锁保护

    3.LinkedList
    基于链表实现

    4.hashSet
    底层用hashMap实现。保存的对象实际上是底层维护的Map对象的key,而value则都是同一个Object对象

    5.TreeSet
    底层是树,实现来自TreeMap。

    6.hashMap
    底层是数组和链表的组合体-散列,有fail-fast保护
    当我们往 HashMap 中 put 元素的时候,先根据 key 的 hashCode 重新计算 hash 值,根据 hash 值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上

    7.TreeMap
    底层用红黑树的排序二叉树来保存Map中的每一个Entry。每一个Entry都被当成“红黑树”的一个节点。当执行put方法时,将该Entry当成一个新节点,添加到已有的红黑树。在插入时,当做排序二叉树来操作即可。由于红黑树可能失衡,则进行调整fixAfterInsertion()
    调整涉及到左旋,右旋,着色三个操作。

    8.hashTable
    底层是Dictionary,实现了fail-fast机制
    key和value都不能为null,会抛出NullPointerException
    所有方法几乎都是synchronized

    9.LinedHashMap
    相比HashMap,其插入的时候是有顺序的,输出的时候可以保持和插入的顺序相同。
    底层通过hash表和双向链表来实现

    10.ConcurrentHashMap
    细分为segment,segment之间允许并发写操作。

    二. JAVA高并发内容

    1. 实现多线程的方式:
      Thead类或者Runnable接口
      Executor线程池

    2.中断线程的方法:
    用stop方法容易导致发生死锁
    最好使用volatile的布尔类型变量自定义一个中断线程的方法

    3.TheadLocal
    线程内部的独立变量,可以保证线程安全
    注意回收:
    TheadLocal.remove()

    4.堆和栈?
    堆是存放对象,以及线程之间的共享变量的。
    栈是线程自己的内存区域,用于存放本地变量,方法参数

    5.重入锁和synchronized相比有什么优点?
    (1)由开发者来控制加锁和释放锁,比较灵活
    (2)可以多次获取同一把锁
    (3)可以临时中断等待锁的申请
    (4)可以限时申请锁,不至于一直等待
    (5)公平锁设定,可以保证不出现饥饿,先来先得

    6.信号量semaphore
    信号量申请和释放的中间临界区可以允许多个线程访问

    7.CountDownLatch和CyclicBarrier
    CountDownLatch是减计数法,减到0后无法重置。
    CyclicBarrier是加计数,加到指定值后重新从0开始(到达指定值之前是阻塞状态)

    8.线程池:
    (1)newFixedThreadPool() 固定大小的线程池
    (2)newScheduledThreadPool() 计划任务调度
    (3)newCachedThreadPool() 缓存型
    (4)SingleThreadExecutor() 只有一个线程
    使用线程池的好处:
    减少在创建和销毁线程上所花的时间以及系统资源的开销
    如果不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存

    9.锁的优化
    (1)减小锁粒度,如hashMap改成ConcurrentHashMap
    (2)使用读写锁代替独占锁
    (3)减小锁的持有时间
    (4)锁粗化,如果连续对同一把锁请求和释放的话,整合这些请求可能会好一些

    10.关于ThreadLocal
    多线程使用同一对象的副本,互不干扰
    底层是ThreadLocalMap,Key是ThreadLocal当前对象,Value就是需要保存的值。使用的是弱引用,在线程结束后,变量就会被回收。

    11.CAS无锁算法(原子类的实现原理-AtomicInteger)
    CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做

    12.如何避免死锁?
    (1)采用无锁函数
    (2)使用重入锁的中断或者限时等待

    13.Fork/Join框架
    有些类似于MapReduce的分而治之的思想。Fork就是把任务分解,Join就是等待前面的执行分支执行完毕。

    14.并发和并行的区别
    并行是真正意义上的同时执行
    而并发是任务之间交替执行

    15.java线程和操作系统线程的关系?
    有相同的线程状态:创建,就绪,执行,阻塞和终止
    OS中线程是用户级线程和内核级线程
    Java的线程是在JVM中实现的,对OS是不可见的

    16.分布式锁的实现
    (1)基于数据库实现分布式锁
    可以基于锁表,或者排他锁(for update语句)
    (2)基于缓存实现,性能较高
    redis sentx(设置超时时间来控制锁释放)
    (3)基于Zookeeper实现,比较可靠
    通过节点变化监听来通知锁获取
    没有单点问题

    JVM内容

    堆内区域:新生代,老年代。新生代是新生的对象会被放置的区域,当对象存活了一定时间后,会被移动到年老代。新生代GC是复制算法,GC比较频繁。老年代一般用标记清除。
    新生代一般不要设置过大,容易导致频繁GC,甚至如果老年代装不下年轻代的变量,会导致频繁的full GC,十分耗时

    相关文章

      网友评论

          本文标题:Java相关

          本文链接:https://www.haomeiwen.com/subject/qvrlfftx.html