1、Log4j日志有几个级别?

由低到高:debug、info、wran、error

2、3*0.1 == 0.3 将会返回什么?true 还是 false?

false,因为有些浮点数不能完全精确的表示出来。

3、什么是内存屏障?

内存屏障,也叫内存栅栏,是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。

4、写一段代码在遍历 ArrayList 时移除一个元素?

该问题的关键在于面试者使用的是 ArrayList 的 remove() 还是 Iterator 的 remove()方法。这有一段示例代码,是使用正确的方式来实现在遍历的过程中移除元素,而不会出现 ConcurrentModificationException 异常的示例代码。

5、AQS支持两种同步方式:

1、 独占式

2、 共享式

这样方便使用者实现不同类型的同步组件,独占式如ReentrantLock,共享式如Semaphore,CountDownLatch,组合式的如ReentrantReadWriteLock。总之,AQS为使用提供了底层支撑,如何组装实现,使用者可以自由发挥。

6、Int与integer的区别

Integer是int的包装类型。

Int的默认值是0,integer的默认值是null

7、在 Java 程序中怎么保证多线程的运行安全?

出现线程安全问题的原因一般都是三个原因:

1、 线程切换带来的原子性问题 解决办法:使用多线程之间同步synchronized或使用锁(lock)。

2、 缓存导致的可见性问题 解决办法:synchronized、volatile、LOCK,可以解决可见性问题

3、 编译优化带来的有序性问题 解决办法:Happens-Before 规则可以解决有序性问题

8、如何选择单例创建方式

如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。 如果需要延迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒韩式。 最好使用饿汉式

  • 代码演示

主要使用懒汉和懒汉式

1、 饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。

2、 懒汉式: 类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。

3、 静态内部方式:结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。

4、 枚举单例: 使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。

5、 双重检测锁方式 (因为JVM本质重排序的原因,可能会初始化多次,不推荐使用)

  • 饿汉式

饿汉式:

类初始化时,会立即加载该对象,线程天生安全,调用效率高。

package com.lijie;

//饿汉式
public class Demo1 {

    // 类初始化时,会立即加载该对象,线程安全,调用效率高
    private static Demo1 demo1 = new Demo1();

    private Demo1() {
        System.out.println("私有Demo1构造参数初始化");
    }

    public static Demo1 getInstance() {
        return demo1;
    }

    public static void main(String[] args) {
        Demo1 s1 = Demo1.getInstance();
        Demo1 s2 = Demo1.getInstance();
        System.out.println(s1 == s2);
    }
}
  • 懒汉式

懒汉式:

类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。

package com.lijie;

//懒汉式
public class Demo2 {

    //类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象。
    private static Demo2 demo2;

    private Demo2() {
        System.out.println("私有Demo2构造参数初始化");
    }

    public synchronized static Demo2 getInstance() {
        if (demo2 == null) {
            demo2 = new Demo2();
        }
        return demo2;
    }

    public static void main(String[] args) {
        Demo2 s1 = Demo2.getInstance();
        Demo2 s2 = Demo2.getInstance();
        System.out.println(s1 == s2);
    }
}
  • 静态内部类

静态内部方式:

结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。

package com.lijie;

// 静态内部类方式
public class Demo3 {

    private Demo3() {
        System.out.println("私有Demo3构造参数初始化");
    }

    public static class SingletonClassInstance {
        private static final Demo3 DEMO_3 = new Demo3();
    }

    // 方法没有同步
    public static Demo3 getInstance() {
        return SingletonClassInstance.DEMO_3;
    }

    public static void main(String[] args) {
        Demo3 s1 = Demo3.getInstance();
        Demo3 s2 = Demo3.getInstance();
        System.out.println(s1 == s2);
    }
}
  • 枚举单例式

枚举单例:

使用枚举实现单例模式 优点:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞, 缺点没有延迟加载。

package com.lijie;

//使用枚举实现单例模式 优点:实现简单、枚举本身就是单例,由jvm从根本上提供保障!避免通过反射和反序列化的漏洞 缺点没有延迟加载
public class Demo4 {

    public static Demo4 getInstance() {
        return Demo.INSTANCE.getInstance();
    }

    public static void main(String[] args) {
        Demo4 s1 = Demo4.getInstance();
        Demo4 s2 = Demo4.getInstance();
        System.out.println(s1 == s2);
    }

    //定义枚举
    private static enum Demo {
        INSTANCE;
        // 枚举元素为单例
        private Demo4 demo4;

        private Demo() {
            System.out.println("枚举Demo私有构造参数");
            demo4 = new Demo4();
        }

        public Demo4 getInstance() {
            return demo4;
        }
    }
}
  • 双重检测锁方式

双重检测锁方式

因为JVM本质重排序的原因,可能会初始化多次,不推荐使用

package com.lijie;

//双重检测锁方式
public class Demo5 {

    private static Demo5 demo5;

    private Demo5() {
        System.out.println("私有Demo4构造参数初始化");
    }

    public static Demo5 getInstance() {
        if (demo5 == null) {
            synchronized (Demo5.class) {
                if (demo5 == null) {
                    demo5 = new Demo5();
                }
            }
        }
        return demo5;
    }

    public static void main(String[] args) {
        Demo5 s1 = Demo5.getInstance();
        Demo5 s2 = Demo5.getInstance();
        System.out.println(s1 == s2);
    }
}

9、Java中的继承是单继承还是多继承

Java中既有单继承,又有多继承。对于Java类来说只能有一个父类,对于接口来说可以同时继承多个接口

10、类与对象的关系?

类是对象的抽象,对象是类的具体,类是对象的模板,对象是类的实例