java积累

编写一个单例模式

1.某个类智能有一个实例
2.它必须自行创建这个实例
3.它必须自行向整个系统提供这个实例
饿汉式: 直接创建对象,不存在线程安全问题
1.直接实例化

public class Singleton {
    public static Singleton INSTANCE = new Singleton();
    private Singleton(){
    }
}

2.枚举

public enum Singleton2 {
    INSTANCE
}

3.静态代码块

public class Singleton3 {

    public static final Singleton3 INSTANCE;

    static {
        //此处可以加载配置文件的信息到类中
        INSTANCE = new Singleton3();
    }

    private Singleton3() {

    }
}

懒汉式: 延迟创建对象
单线程下安全

public class Singleton3 {

    private static Singleton3 instance;

    private Singleton3() {

    }

    public static Singleton3 getInstance() {
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;

    }
}

如果对象创建时间长,则有可能出现多次创建对象的情况

public class Singleton3 {

    private static Singleton3 instance;

    private Singleton3() {

    }

    public static Singleton3 getInstance() throws InterruptedException {
        if (instance == null) {
            Thread.sleep(1000);
            instance = new Singleton3();
        }
        return instance;

    }
}

多线程测试代码:

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        Callable<Singleton3> c = new Callable<Singleton3>() {
            @Override
            public Singleton3 call() throws Exception {
                return Singleton3.getInstance();
            }
        };

        ExecutorService es = Executors.newFixedThreadPool(2);

        Future<Singleton3> f1 = es.submit(c);
        Future<Singleton3> f2 = es.submit(c);
        System.out.println(f1.get());
        System.out.println(f2.get());

    }

解决办法:
getInstance增加synchronize

 public static Singleton3 getInstance() throws InterruptedException {
        synchronized (Singleton3.class){
            if (instance == null) {
                Thread.sleep(1000);
                instance = new Singleton3();
            }
            return instance;
        }


    }

改进效率版本:在执行同步前增加一层判断,这样不会都走到线程安全块的代码

 public static Singleton3 getInstance() throws InterruptedException {
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    Thread.sleep(1000);
                    instance = new Singleton3();
                }

            }
        }
        return instance;
    }

静态内部类:当调用getInstance时才会执行内部类的方法,内部类不会随着外部类的初始化而初始化

public class Singleton3 {
    private Singleton3() {

    }

    private static class Inner {
        private static Singleton3 instance = new Singleton3();
    }

    public static Singleton3 getInstance() throws InterruptedException {
        return Inner.instance;
    }
}

类初始化过程

样例代码

public class Father {
    private int i = test();
    private static int j = method();

    static {
        System.out.print("(1)");
    }

    Father() {
        System.out.print("(2)");
    }

    {
        System.out.print("(3)");
    }

    public int test() {
        System.out.print("(4)");
        return 1;
    }

    public static int method() {
        System.out.print("(5)");
        return 1;
    }

}

public class Son extends Father {
    private int i = test();
    private static int j = method();

    static {
        System.out.print("(6)");
    }

    Son() {
        System.out.print("(7)");
    }

    {
        System.out.print("(8)");
    }

    public int test() {
        System.out.print("(9)");
        return 1;
    }

    public static int method() {
        System.out.print("(10)");
        return 1;
    }

    public static void main(String[] args) {
        Son s1 = new Son();
        System.out.print("");
        Son s2 = new Son();
    }
}

结果为: (5)(1)(10)(6)(9)(3)(2)(9)(8)(7)(9)(3)(2)(9)(8)(7)

1.包含static的变量和方法按照顺序执行,从父类到子类,所以是 (5)(1)(10)(6)
2.实例初始化过程: 非静态实例变量显式赋值代码和非静态代码块代码从上往下执行,而对应的构造器最后执行
子类实例化方法:
(1) 调用super()
(2) 非静态变量
(3) 非静态代码块
(4) 子类无参构造器
注意方法的重写问题,非静态方法前面是隐藏着一个this对象,指向正在创建的对象
所以实例中父类的test方法其实是调用了子类的test方法

  • final方法,静态方法,private等子类中不可见方法是不能被override的,所以静态方法中不存在这个问题

变量




如果没有this,则变量遵循就近原则
成员变量保存在堆中,局部变量保存在栈中
实例:

public class Exam5 {
    static int s;
    int i;
    int j;

    {
        int i = 1;
        i++;
        j++;
        s++;
    }

    public void test(int j) {
        j++;
        i++;
        s++;
    }

    public static void main(String[] args) {
        Exam5 obj1 = new Exam5();
        Exam5 obj2 = new Exam5();
        obj1.test(10);
        obj1.test(10);
        obj2.test(30);
        System.out.println(obj1.i + "," + obj1.j + "," + obj1.s);
        System.out.println(obj2.i + "," + obj2.j + "," + obj2.s);
    }
}

输出结果为
2,1,5
1,1,5

bean作用域

在spring中可以在元素的scope属性设置bean作用域,决定这个bean是单实例还是多实例

spring支持的常用数据库事务和隔离级别

事务传播属性:当事务方法被另一个事务方法调用时,必须指定事务如何传播,例如方法可以继续在现有事务运行,也可能开启一个新的事务,并在自己的事务中运行
@Transactional 默认为REQUIRED,使用原来的事务
7种事务传播属性:

常用的是REQUEST和REQUEST_NEW
REQUEST:

REQUEST_NEW:

数据库隔离级别

脏写和脏读: 无论是脏写还是脏读,都是因为一个事务去更新或者查询了另外一个还没提交的事务更新过的数据。因为另外一个事务还没提交,所以它随时可能会回滚,那么必然导致你更新的数据就没了,或者你之前查询到的数据就没了,这就是脏写和脏读两种场景。
不可重复读: 事务A开始一个读事务,然后事务B更新值,然后事务C更新值,导致A事务在多次读的时候数据不一致
如果你希望看到的场景是不可重复读,也就是事务 A 在执行期间多次查询一条数据,每次都可以查到其它已经提交的事务修改过的值,那么就是不可重复读,如果你希望这样子,那也没问题。
如果你期望的是可重复读,但是数据库表现的是不可重复读,让你事务 A 执行期间多次查到的值都不一样,都的问题是别的提交过的事务修改过的,那么此时你就可以认为,数据库有问题,这个问题就是「不可重复读」
幻读: 就是你一个事务用一样的 SQL 多次查询,结果每次查询都会发现查到一些之前没看到过的数据。注意,幻读特指的是你查询到了之前查询没看到过的数据。此时说明你是幻读了

SpringMVC中怎样避免post中文乱码,get中文乱码

post请求: 增加CharacterEncodingFilter
get请求: 修改tomcat的server.xml 在Connector标签中配置URIEncoding="utf-8"

mybatis中当实体类的属性名和表中字段名不一样怎样处理

1.写sql时写别名
2.mybatais开启驼峰命名
3.resultMap映射

redis持久化




Elasticsearch和solr区别

都是基于lucene搜索引擎
都是基于java开发
Solr:2004年诞生
ES:2010年诞生
solr利用zookeeper进行分布式管理
es自身电邮分布式管理

posted @ 2021-03-10 19:46  余***龙  阅读(73)  评论(0编辑  收藏  举报