欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面试必备系列-Java基础相关(二)

程序员文章站 2024-03-23 12:14:46
...

java是引用传递还是值传递

引用知乎的一位大神的理解,讲的很到位。

https://www.zhihu.com/question/31203609

ThreadLocal为什么会内存泄露

ThreadLocal我们通常会用在一个线程里面共享一个变量,通过ThreadLocal.set()

方法将变量数据放进去。

 1public void set(T value) {
 2          // 获取当前线程
 3        Thread t = Thread.currentThread();
 4          // 获取ThreadLocalMap
 5        ThreadLocalMap map = getMap(t);
 6        if (map != null)
 7              // 不为空,则放入进去
 8            map.set(this, value);
 9        else
10              // 为空,则创建一个ThreadLocalMap,然后将值放进去
11            createMap(t, value);
12}

每个Thread 中都有个ThreadLocalMap, 这个MAP中key为ThreadLocal ,value为存储的值。 其中key为弱引用。

弱引用的定义: 如果外部没有强引用对他引用,那么他将在最近的一次GC被回收。

所以在ThreadLocal外部引用他的对象被回收了,那么ThreadLocal也将被回收, 这就导致了ThreadLocalMap中

存在key的引用为null, 但是value不为空的情况。

针对上面那种情况,ThreadLocalMap在下次set ,get,remove的时候,会自动清除掉key为null的value。

内存泄露的原因

ThreadLocalMap中存在大量key为null的value,但是线程一直无法结束,同时也没有继续调用get,set,remove

方法,这就导致了map中有大量的value无法被清除。 因此导致内存泄露。 泄露的根本原因是因为ThreadLocalMap的生命周期和Thread一致。 如过Thread短时间不结束。那么ThreadLocalMap也不会被回收。

JVM针对这种情况做出的优化
1.ThreadLocalMap的key(ThreadLocal)采用弱引用,因此在使用ThreadLocal的对象被回收,key在下次GC也会被回收

2.在ThreadLocalMap get,set ,remove的会清除掉key为null的value

通过以上两个机制,JVM尽可能的保证不发生内存泄露,但是做不到根治。

Rentrantlock和synchronized的区别

synchronized是JVM的实现 , 发生异常时,JVM会自动释放锁,JDK1.6之前性能较差,1.6之后,synchronized也

采用了CAS的操作,性能大幅度提高。

Rentrantlock是基于AQS实现的,lock()之后必须在finallylim调用unlock() , 提供了更多的API,可以完成更多的功能,比如tryLock()尝试获取锁,如果获取不到锁则不必继续等待。 同时提供了公平锁和非公平锁的选择。

详情可以看: https://blog.csdn.net/u012394095/article/details/80518594

synchronized相关问题

 1public class Demo1 {
 2    public synchronized static  void add(){
 3        System.out.println("add");
 4    }
 5    public  static  void edit(){
 6        synchronized (Demo1.class){
 7            System.out.println("edit");
 8        }
 9    }
10}

如上所示,add方法和edit方法能够做到互斥吗?

答案是可以的,静态方法上加synchronized,锁住的就是Demo1这个class对象。

ThreadPoolExecutor几个参数的作用

1corePoolSize : 核心线程池大小
2maximumPoolSize : 最大线程数量
3keepAliveTime : 超出核心线程池大小的线程过多少时间回收
4unit : keepAliveTime的单位
5workQueue : 当核心线程池已经满了的并且没有空闲的线程时,任务放入到队列中
6threadFactory : 产生线程的工厂,我们可以自定义,比如说,对线程命名,根据一定的规则产生
7同时可以设定线程是否是守护线程
8RejectedExecutionHandler : 当队列满了,最大线程数也满了,那么就要根据拒绝策略来决定任务的去留

ThreadPoolExecutor的拒绝策略

AbortPolicy : 直接拒绝,报异常

CallerRunsPolicy : 直接在execute方法中调用线程的run方法,如果线程池已经关闭,则丢弃该任务

DiscardOldestPolicy : 丢弃最早的那个任务,也就是队列中的第一个任务,然后重新调用execute方法

DiscardPolicy : 直接丢弃,不做任何处理


面试必备系列-Java基础相关(二)

上一篇: java集合框架、面试

下一篇: