Java热点知识回顾
简述JVM 垃圾回收机制
一个普通的应用程序运行时会有很多临时对象,为了避免临时对象频繁的创建和删除导致内存碎片的产生,JVM将内存堆划出了一小片区域,叫做新生代区,专门用来做这种临时对象的快速垃圾回收。当新生代中放不下或者存活较久的会被放到另一块较大的内存区中,这个较大的内存区叫做老年代。如果老年代放满了,就会触发一次全堆的内存回收,把不老年代中的堆空间释放出来。一般不需要手动调用GC方法,即使调用了JVM也不会立即执行。
Java的函数式接口有哪些
Function 接受一个泛型参数,返回一个泛型结果
Consumer 接受一个泛型参数,无返回结果
Supplier 无参数,返回一个泛型结果
Predicate 接受一个泛型参数,返回一个bool结果
Callable 泛型接口,call方法返回泛型结果
Runable 无泛型,接口,执行run方法指定的内容
Java有哪些锁机制:
https://www.cnblogs.com/xiaoxi/p/9140541.html ReentrantReadWriteLock读写锁详情
ReentrantReadWriteLock 可重入锁。读的过程中不可以写,但是其他的读可以进。
StampedLock 乐观读锁,是不可重入锁,如果当前线程已经获取了写锁,再次重复获取写锁的话就会死锁;读的过程中可以写,读完之后需要校验是否有写锁介入,如果有就需要重新读
https://blog.csdn.net/tongdanping/article/details/79647337 Java并发锁升级详解
锁升级(随着竞争加剧,锁的实现代价逐渐加大),锁粗化(多个连续的加锁和解锁,优化为一个锁,避免频繁的线程切换),锁消除(JIT编译时,经过逃逸分析,认为不会存在竞争,去掉锁)
逃逸分析 https://zhuanlan.zhihu.com/p/401057707
Javat同步锁?https://blog.csdn.net/xindanding/article/details/103854191
读写锁ReadWriteLock: 对同一临界区资源进行访问的线程.如果已经有写线程占用锁,读线程和写线程需要等待;如果有读线程占有锁,写线程需要等待,读线程不需要等待
信号量Semaphore: 对临界区资源进行同步后,所有对临界区资源进行访问的线程都得串行排队,而信号量允许指定的线程数同时进行访问;(适用于资源有最高限度,类似于有限座位数)
计数器CountDownLatch: 计数器会指定线程数量num,程序会等待至少 num个线程执行完成才往下继续执行;(适用于资源有最低限度要求,类似团购)
循环栅栏CyclicBarrier: 栅栏就是障碍物,所有共用这个栅栏中的每个线程都得等待,直到所有线程都等待,则往下执行;循环栅栏可以多次使用
公平锁与非公平锁
公平锁会尽量以请求到达的顺序来获取锁,从而保证先来先服务。
非公平锁无法保证锁的分发顺序,可能会导致极端情况下一个县城一直无法获取到锁。synchronize是非公平锁,ReentrentReadWriteLock可以设置使用公平或非公平锁。非公平锁比公平锁的性能要高,因为公平锁需要维护一个队列,如果当前县城不是队列的第一个元素则无法获取锁,增加了县城切换的次数。
为什么要使用synchronize
例如自己实现一个线程安全的队列,需要用到synchronize 对添加和删除方法。
synchronize是不可中断的,一旦使用会强制等待。而lock是可以判定是否成功获得锁的,如果一次没有获取到锁,是可以取消操作的。一般我们加锁的地方都是不可中断的,所以优先选择synchronize。只有在一些非常确认读多写少的地方才会使用读写锁。
什么是CopyOnWrite容器
CopyOnWrite容器使用的是一种读写分离的思想,每次写入时都复制一个新容器出来,将新元素写入。好处是可以并发读,不需要加读锁。只有并发写入和删除才需要加锁。
缺点是读的时候会读到旧数据。此类容器多用于读多写少,不需要强一致性的场景。同时,大量CopyOnWrite 会产生内存占用问题,因为复制时占用了两倍的内存空间。或者使用Concurrent并发容器对象替代。
限流熔断方案
令牌桶,RateLimiter:设定令牌上限,以恒定的速度产生令牌,每个请求发送一个令牌,获取不到令牌的请求就丢弃。
Concurrent并发包下的内容:
Atomic 系列
Concurrent系列:ConcurrentHashmap,ConcurrentSkipList
Semaphore,CountDownLatch
CopyOnWrite系列:CopyOnWriteArrayList
Java 强引用,软引用,弱引用,虚引用
强引用:不会被回收的引用
软引用:内存不足时(比如触发FullGC时),会被系统自动回收。一般用来描述有用但不是非必须的对象,比如一些缓存数据。
弱引用:当垃圾回收时(比如YungGC),若对象只被WeakReference对象的弱引用,就会被回收。弱引用一般用来描述非必需对象。
虚引用:任何时候都可能被回收。一般会关联到一个队列,当虚引用队列对象被回收时,会被放入引用队列中。
ThreadLocal 使用的是弱引用,一般将ThreadLocal对象设计为static,防止其作为临时变量在执行完任务之后,key被回收,value未被回收而导致部分内存泄漏。但ThreadLocal内部存在一定防御机制,当get,set,和扩容的时候会自动判断key是否已被回收,一般会自动清理一部分。get时通过setInitValue(null)实现的。
java 泛型限定符中,extend 与 super
extends 固定上边界,其中的类型都是T的子类
List<? extends Number> Number <- Integer,Double,Long
使用 extends 意味着该变量为数据的提供者,你可以从集合中读取出T或T的子类对象,但是不能向其中添加数据,会报错。
super 固定下边界,其中的类型都是T的父类。
List<? super Integer> Integer -> Number -> Object 可写不可读
使用 super 意味着该变量为数据的消费者,集合可以新增数据,但是不能读取数据,因为你不知道读出来的会是什么类型。因此拿出来的都是Object
关于泛型的错误:
ArrayStoreException:装猫的笼子在概念上被转换为装动物的笼子,然后塞了一只狗?所以放狗的时候会报错。更近一步,如果new的是WhiteCat,也不能往里面放Cat。
Cat[] cats = new Cat[2]; // Cat[] cats = new WhiteCat[2]; ??
Animal[] animals = cats;
cats[0] = new WhiteCat();
animals[1] = new Dog();
编译错误,类型不匹配:猫的泛型抽象不能被转换为动物的泛型抽象。
AnimalT<Cat> cc = new AnimalT<>();
AnimalT<Animal> ca = cc;
内部类与静态内部类
二者编译后都会产生[NAME]$[NAME].class文件;
静态内部类只能范围外部类的静态方法和变量,因为它单独存在,可以完全独立于外部类存在。只是利用外部类来隐藏自己。只是为了方便类的使用而放到类的内部而已。
非静态的内部类可以访问外部类的所有方法和变量,但是它只能被外部类的实例化对象调用。有了实例化对象,才可以访问。
Java线程池拒绝策略
当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中。当阻塞队列饱和后,才会扩充线程池中线程数,直到达到 maximumPoolSize 最大线程数配置。此时,再多余的任务,则会触发线程池的拒绝策略了。
总结起来,也就是一句话,当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略。
jdk 默认的拒绝策略是:AbortPolicy
AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
DiscardPolicy:直接丢弃任务,并且不进行任何操作。
DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务;
CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务;
如果线程池中的线程在执行任务的时候,抛异常了,会怎么样?
任务的 task.run() 在 while 无限循环中执行,while 被 try finally包裹,当异常发生时,finally执行processWorkerExit
方法,将异常的线程移除,如果线程池没有关闭,就另外新建一个线程。
如何修改原生线程池,使得可以先拉满线程数再入任务队列排队?
原生线程池的execute
方法中,调用了workQueue.offer
方法,返回true时,入队成功,返回false 入队失败。我们可以通过自定义任务队列,重写 offer方法,当线程数量没满时,返回false即可让线程池创建额外的线程。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 using1174@foxmail.com
文章标题: Java热点知识回顾
文章字数: 2,339
本文作者: Jun
发布时间: 2022-03-14, 15:20:00
最后更新: 2022-05-23, 10:35:26
原始链接: http://yoursite.com/2022/03/14/Java热点知识回顾/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。