第一次Java面试复盘

54 阅读3分钟

核心问题:不知道提问重点

1. StringBuffer和StringBuilder的区别(线程安全与不安全)

2. Java常见数据结构(set,List,Map,Tree)

3. Java死锁问题

一、死锁的产生的原因

 * 描述: 必定死锁的情况
 */
public class MustDeadLock implements Runnable {

    public int flag;
    static Object o1 = new Object();
    static Object o2 = new Object();

    public void run() {
        System.out.println("线程"+Thread.currentThread().getName() + "的flag为" + flag);
        if (flag == 1) {
            synchronized (o1) {
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized (o2) {
                    System.out.println("线程1获得了两把锁");
                }
            }
        }
        if (flag == 2) {
            synchronized (o2) {
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized (o1) {
                    System.out.println("线程2获得了两把锁");
                }
            }
        }
    }

    public static void main(String[] argv) {
        MustDeadLock r1 = new MustDeadLock();
        MustDeadLock r2 = new MustDeadLock();
        r1.flag = 1;
        r2.flag = 2;
        Thread t1 = new Thread(r1, "t1");
        Thread t2 = new Thread(r2, "t2");
        t1.start();
        t2.start();
    }
 }

死锁的产生有四个必要的条件

互斥使用,即当资源被一个线程占用时,别的线程不能使用

不可抢占,资源请求者不能强制从资源占有者手中抢夺资源,资源只能由占有者主动释放

请求和保持,当资源请求者在请求其他资源的同时保持对原因资源的占有

循环等待,多个线程存在环路的锁依赖关系而永远等待下去,例如T1占有T2的资源,T2占有T3的资源,T3占有T1的资源,这种情况可能会形成一个等待环路

4. 非静态方法可以调用静态成员变量吗

1.静态成员变量和静态成员方法都是属于类的,静态成员(包括属性和方法)是在类加载阶段就已经初始化了的,所以当某一个实例访问静态成员的时候,静态成员肯定是已经存在了的,所以实例的非静态方法可以调用静态成员变量。

2.反过来,如果让静态方法去访问实例成员那就不行了,因为实例成员的初始化在静态成员之后

5. arrayList循环内能否添加成员

6. ==和equals的区别

  • ==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。 (比较地址值即是指是否为同一个对象的引用)

  • equals()是一个方法,只能比较引用数据类型。

//例子一:对象不同,内容相同,”==”返回falseequals返回true
String s1 = new String("java");
String s2 = new String("java");

System.out.println(s1==s2);            //false
System.out.println(s1.equals(s2));    //true
//例子二:同一对象,”==”和equals结果相同
String s1 = new String("java");
String s2 = s1;

System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));    //true

8.数据库调优

索引将通过缩小一张表中需要查询的记录的数目来加快搜索的速度。如果没有索引,数据库不得不进行全表扫描。好比一本书的目录,它会让你更快的找到内容。 索引的数据结构:B树变种B+树,hash索引 为什么用B+树?

磁盘读写代价更低: B树其实最开始源于的是二叉树,二叉树是只有左右孩子的树,当数据量越大的时候,二叉树的节点越多,那么当从根节点搜索的时候,影响查询效率。所以如果这些节点存储在外存储器中的话,每访问一个节点,相当于进行了一次I/O操作。 B+树的多路搜索可以减少访问的节点次数,也就是减少I/O操作次数,这就使以页为单位的索引中可以存放更多的节点

B+树的性能缺点:会产生大量的随机IO,主要存在以下两种缺点: 主键不是有序递增的,导致每次插入数据产生大量的数据迁移和空间碎片;即使主键是有序递增的,大量写请求的分布仍是随机的;