java高频面试题目记录一
程序员文章站
2022-04-17 17:45:36
...
程序题–自增变量
源自B站视频:传送门
这里注意容易出错的地方是上图右边步骤中的2,5 自增是在局部变量表中自增。而赋值操作是将操作数栈里的数赋值给局部变量表对应的变量。
编程题–写一个单例设计模式
饿汉式的三种创建方式
1:直接实例化
/*
*饿汉式
*在类初始化的时候,直接创建实例对象,不管你是否需要这个对象,都会创建
*
* (1)构造器私有化
* (2)自行创建,并保存在静态变量中
* (3)对外提供获取该实例对象的方式--public
* (4)强调单例,用final修饰(final修饰的一般为常量,因此instance改为大写)
*/
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();//饿汉式直接创建实例对象
private Singleton1() {
}
}
2:枚举式
/*
* 枚举类型代表该类型对象是有限的几个
* 我们可以限定为只有一个,就成为单例了
* 更简洁了
*
*/
public enum Singleton2 {
INSTANCE
}
3:静态代码块
public class Singleton3 {
public static final Singleton3 INSTANCE ;
private String info;
//在静态代码块中实例化,也是在类加载和初始化过程中,静态常量便创建出来
static {
try {
//从配置文件去读取info值,配置文件放在src下,用类加载器去加载
//静态代码块适用于比较复杂的,需要读一堆初始化数据的
Properties properties = new Properties();
properties.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
//用当前类得类加载器去加载配置文件
INSTANCE = new Singleton3(properties.getProperty("info"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
single.properties文件放上我们想要的数据
#key=value
info=abc
上述三种方式的测试
懒汉式的三种创建方式
1:线程不安全
package singleton;
/*
* (1)构造器私有化
* (2)不自行创建,只定义一个静态变量
* (3)提供一个静态方法,获取实例对象
*/
public class Singleton4 {
private static Singleton4 instance;
//这里就不能public,因为我们没有给他创建对象,那么直接这样调用,可能是个空对象
private Singleton4() {
}
public static Singleton4 getInstance(){
if(instance==null) {
//测试当两个线程,先后进入到这里休眠,那么就会创建两个实例,所以这个例子存在线程安全问题
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
instance = new Singleton4();
}
return instance;
}
}
测试代码:
public class TestSingleton4 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<Singleton4> c = new Callable<Singleton4>() {
@Override
public Singleton4 call() throws Exception {
// TODO Auto-generated method stub
return Singleton4.getInstance();
}
};
/*
* 启动线程服务
* 创建线程池
* 提交线程服务
*/
ExecutorService eService =Executors.newFixedThreadPool(2);
Future<Singleton4> future1 = eService.submit(c);
Future<Singleton4> future2 = eService.submit(c);
Singleton4 s1 = future1.get();
Singleton4 s2 = future2.get();
System.out.println(s1 == s2);
eService.shutdown();
}
}
因此线程不安全,返回的是false,
2:线程安全
package singleton;
/*
* (1)构造器私有化
* (2)不自行创建,只定义一个静态变量
* (3)提供一个静态方法,获取实例对象
*/
public class Singleton5 {
private static Singleton5 instance;
//这里就不能public,因为我们没有给他创建对象,那么直接这样调用,可能是个空对象
private Singleton5() {
}
public static Singleton5 getInstance(){
//添加一个同步锁,保证线程安全
//为了保证线程安全得同时,提供效率,把对instance==null得判断放在锁得外面
if(instance==null) {
synchronized (Singleton5.class) {
if(instance==null) {
//测试当两个线程,先后进入到这里,休眠,那么就会创建两个实例,所以这个例子存在线程安全问题
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
instance = new Singleton5();
}
}
}
return instance;
}
}
同样的测试线程安全,返回的是true,
3:静态内部类
package singleton;
/*
* 在内部类加载和初始化时,才创建instance实例对象
* 静态内部类不会随着外部类得加载和初始化而初始化,它是要单独去加载和初始化得
*因为是在内部类加载和初始化时创建得,因此是线程安全的
*/
public class Singleton6 {
private Singleton6() {
}
private static class Inner {
private static Singleton6 instance = new Singleton6();
}
public static Singleton6 getInstance() {
return Inner.instance;
}
}
小结
如果是饿汉式,枚举形式最简单
如果是懒汉式,静态内部类形式最简单
上一篇: 迎八一,军人的幽默
下一篇: 爆笑的军旅生活笑话大全