Skip to content

1、堆的作用是什么?

是虚拟机所管理的内存中最大的一块,被所有线程共享的,在虚拟机启动时创建。堆用来存放对象实例,Java 里几乎所有对象实例都在堆分配内存。堆可以处于物理上不连续的内存空间,逻辑上应该连续,但对于例如数组这样的大对象,多数虚拟机实现出于简单、存储高效的考虑会要求连续的内存空间。

堆既可以被实现成固定大小,也可以是可扩展的,可通过 -Xms-Xmx 设置堆的最小和最大容量,当前主流 JVM 都按照可扩展实现。如果堆没有内存完成实例分配也无法扩展,抛出 OutOfMemoryError。

2、为什么HashTable是线程安全的?

因为HasTable的内部方法都被synchronized修饰了,所以是线程安全的。其他的都和HashMap一样

1、 HashMap添加方法的源码

2、 HashTable添加方法的源码

3、stackoverflow错误,permgen space错误

stackoverflow错误主要出现:

在虚拟机栈中(线程请求的栈深度大于虚拟机栈锁允许的最大深度)

permgen space错误(针对jdk之前1.7版本):

1、 大量加载class文件

2、 常量池内存溢出

4、Java 中你怎样唤醒一个阻塞的线程?

首先 ,wait()、notify() 方法是针对对象的,调用任意对象的 wait()方法都将导致线程阻塞,阻塞的同时也将释放该对象的锁,相应地,调用任意对象的 notify()方法则将随机解除该对象阻塞的线程,但它需要重新获取该对象的锁,直到获取成功才能往下执行;

其次,wait、notify 方法必须在 synchronized 块或方法中被调用,并且要保证同步块或方法的锁对象与调用 wait、notify 方法的对象是同一个,如此一来在调用 wait 之前当前线程就已经成功获取某对象的锁,执行 wait 阻塞后当前线程就将之前获取的对象锁释放。

5、JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代?

当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区。大对象(需要大量连续内存空间的Java对象,如那种很长的字符串)直接进入老年态;如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15),则被晋升到老年态。即长期存活的对象进入老年态。老年代满了而无法容纳更多的对象,Minor GC 之后通常就会进行Full GC,Full GC 清理整个内存堆 – 包括年轻代和年老代。Major GC 发生在老年代的GC,清理老年区,经常会伴随至少一次Minor GC,比Minor GC慢10倍以上。

6、你熟悉哪些垃圾收集算法?

标记清除(缺点是碎片化) 复制算法(缺点是浪费空间) 标记整理算法(效率比前两者差) 分代收集算法(老年代一般使用“标记-清除”、“标记-整理”算法,年轻代一般用复制算法)

7、CMS分为哪几个阶段?

CMS已经弃用。生活美好,时间有限,不建议再深入研究了。如果碰到问题,直接祭出回收过程即可。

1、 初始标记

2、 并发标记

3、 并发预清理

4、 并发可取消的预清理

5、 重新标记

6、 并发清理

由于《深入理解java虚拟机》一书的流行,面试时省略3、4步一般也是没问题的。

8、创建线程的四种方式

继承 Thread 类;

public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " run()方法正在执行...");
}

实现 Runnable 接口;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " run()方法执行中...");
}

实现 Callable 接口;

public class MyCallable implements Callable<Integer> {

@Override
public Integer call() {
    System.out.println(Thread.currentThread().getName() + " call()方法执行中...");
    return 1;
}

使用匿名内部类方式

public class CreateRunnable {
    public static void main(String[] args) {
        //创建多线程创建开始
        Thread thread = new Thread(new Runnable() {
                    public void run() {
                    for (int i = 0; i < 10; i++) {
                    System.out.println("i:" + i);
                }
            }
        });
        thread.start();
    }
}

9、说一下 runnable 和 callable 有什么区别

相同点:

1、 都是接口

2、 都可以编写多线程程序

3、 都采用Thread.start()启动线程

主要区别:

Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果

Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出异常,可以获取异常信息 注:Callalbe接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执行,如果不调用不会阻塞。

10、为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object 类里?

Java的每个对象中都有一个锁(monitor,也可以成为监视器) 并且wait(),notify()等方法用于等待对象的锁或者通知其他线程对象的监视器可用。在Java的线程中并没有可供任何对象使用的锁和同步器。这就是为什么这些方法是Object类的一部分,这样Java的每一个类都有用于线程间通信的基本方法。

11、什么叫线程安全?servlet是线程安全吗?

12、Java会存在内存泄漏吗?请简单描述。

13、JVM 出现 fullGC 很频繁,怎么去线上排查问题

14、GC 垃圾收集器

15、不可变对象对多线程有什么帮助

16、线程之间是如何通信的?

17、为什么需要双亲委派模式?

18、Java线程池中submit() 和 execute()方法有什么区别?

19、形成死锁的四个必要条件是什么

20、什么是多线程中的上下文切换?

21、标记清除算法( Mark-Sweep)

22、遇到过堆外内存溢出吗?

23、谈谈你知道的垃圾回收算法

24、运行时数据区是什么?

25、CyclicBarrier和CountDownLatch的区别

26、Java线程具有五中基本状态

27、什么是原子类

28、ArrayList和Vector有什么不同之处?

29、什么是方法内联?

30、JVM怎么判断一个对象是不是要回收?

31、调优命令有哪些?

32、java如何实现多线程之间的通讯和协作?

用心去做高质量的内容网站,欢迎 star ⭐ 让更多人发现