前言
面试的时候常被问到的问题,今天就来做下复盘,并且以问答的形式来简答一下。
start
1、内存泄漏
内存泄漏字面上的意思就是内存不受管控了,一般是指内存不可以被回收也不可以被利用,一般什么情况下会发生内存泄漏?比如使用static修饰的变量,比如使用private static Map map = new HashMap();如果使用该map保存了一个临时对象,如果一个临时对象用完之后本来就没有用会被垃圾回收器回收,结果因为保存在了static修饰的map中,导致回收不了。
2、内存抖动
刚听到这个词我的第一反应是内存中数据丢失,结果看了相关资料才明白内存抖动就是频繁的内存申请和释放,呈现出的内存图像是一把锯齿。常见的场景就是创建一个数组,然后频繁的扩容。
3、死锁以及死锁的构造
死锁顾名思义就是无法解开的锁,一般有两层含义,一种一个线程持有锁后,长时间不释放,对于其他线程而言等待会超时,那么这种也会认为是死锁,比如mysql中超大事务的操作对表增加了表锁,导致其他线程不能操作该表。另一种就是多个线程相互等待对方释放锁,最终导致永远也不会释放锁。
构造一个死锁:如果两个变量第一个线程处理后第二个线程才能处理。那么下面的程序将会陷入死锁状态。
public class TestLock {
public static void main(String[] args) throws InterruptedException {
final int[] a = {0};
final int[] b = {1};
final CountDownLatch countDownLatch = new CountDownLatch(2);
Lock lock = new ReentrantLock();
for (final int[] i = {0}; i[0] <2; i[0]++) {
int finalI = i[0];
new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
if (finalI == 0 && b[0] == 0 && lock.tryLock()) {
a[0]++;
lock.unlock();
System.out.println("释放锁1" + Thread.currentThread().getName());
}
if (finalI == 1 && a[0] == 1 && lock.tryLock()) {
b[0]--;
lock.unlock();
System.out.println("释放锁2" + Thread.currentThread().getName());
}
if (lock.tryLock()) {
countDownLatch.countDown();
}
}
}).start();
}
// 等待所有线程执行完毕
countDownLatch.await();
}
}
补充一个特殊的内存泄漏: 单例模式内存泄漏:
public class MySingleton {
private static MySingleton instance = null;
private ArrayList<String> myList;
private MySingleton() {
myList = new ArrayList<String>();
}
public static MySingleton getInstance() {
if(instance == null) {
instance = new MySingleton();
}
return instance;
}
public void addItem(String item) {
myList.add(item);
}
}
这是有个典型的单例模式,在这个例子中,MySingleton类使用了一个ArrayList来存储数据。每次调用addItem方法时,都会将一个新的String对象添加到ArrayList中。但是,MySingleton类仅在其第一次调用getInstance方法时进行实例化,这意味着所有addItem调用都是在同一个实例上进行的。
由于Java的垃圾回收机制是基于引用计数的,因此只要MySingleton实例存在,它所持有的ArrayList也会一直存在。这意味着,如果程序在不需要MySingleton实例时不显式地将其清空,那么ArrayList也将一直存在并占用内存,导致内存泄漏。
为了避免这种情况,我们可以选择在不需要MySingleton实例时,将其引用设置为null,强制Java垃圾回收机制回收相关的内存。例如:
MySingleton instance = MySingleton.getInstance();
// 使用MySingleton实例
instance = null;