1.hashMap,ConcurrentHashMap,hashTable的区别
hashMap是线程不安全的,ConcurrentHashMap,hashTable是线程安全的
hashTable是锁整个Map,所有对map的操作都会锁住,性能很差,不推荐使用
ConcurrentHashMap本质上是把hashmap分成了很多个Segment,等同于很多个hashTable,根据hash值存储和获取,操作时,只会锁住对应的Segment,而不会锁住整个Map,既保证了线程安全又不会降低
多线程环境下ConcurrentHashMap比做了同步的hashmap好,单线程环境下hashmap性能更好
2.java的注解
其实和接口类似,属于继承接口的接口,作用主要是标记,用于生成文档,注入信息,获取注解类示例用于注入等;
分为元注解和自定义注解,元注解有4个,Target用于标记注解范围(类上用还是方法上用),Retention 用于标记使用时机(运行时用还是编译时用),还有两不常用,用于生成文档或者标记子类是否继承
spring注解实际是依赖注解和反射,通过包扫描扫描注解,然后用反射获取对应类,在容器中进行注册,初步理解按扫描到的bean构造,构造时发现有依赖则地则先初始化依赖内容,后续再扫描autoWired进行注入
3.java的接口
接口的主要作用是用于统一标准和规范,降低耦合,减少重复开发量
对于多个对象包含同一方法时,通过定义接口,只需对方法进行一次调用,通过注入不同对象,达成多个对象的方法实现
比如绘图方法,100种绘图类会绘制100个图案,如果不用接口,就要调用100次绘画的方法,如果使用接口,定义一个绘图工具接口,之后只需要写一遍绘图的方法,只要通过注入不同对象,就可以绘制出不同的图
拿Runnable接口举例,线程实例必须实现Runnable方法中的run方法,创建Thread对象时,只接收Runnable对象,将该线程实例作为Runnable对象传入,之后执行Thread的start方法,同时调用实例中的run方法
接口的意义在于,如果不实现接口,传入对象后根本不知道里面包含了什么方法,也无法调用,唯一的办法只能用反射遍历此对象中存在的方法, 按方法名匹配,而且不一定能找到,这样还会暴露整个对象的全部方法
实现了接口以后,不关心对象本身,只关心对象中的run方法,并进行调用
4.volatite的作用
java内存模型围绕原子性,可见性,有序性来进行,
volatite无法保证原子性,但可以保证可见性以及一定程度上保证有序性
5.jdk1.8的新特性
1.接口可以增加默认实现,需要default关键字,并且可以使用箭头的方式实现接口
2.lambda表达式,用于简化匿名内部类的写法
(String a, String b) -> { return b.compareTo(a); }
3.函数式接口,所谓函数式接口(Functional Interface)就是只包含一个抽象方法的声明。针对该接口类型的所有 Lambda 表达式都会与这个抽象方法匹配。{另外,只是在接口上添加default并不算抽象方法}
4.Lambda的作用范围
(1)局部变量,但局部变量不能发生改变
(2)成员和静态,可以修改
5.optionals,用来防空指针异常,不确定一个对象是否可能为空时可以用此类型包装
6.map,可以直接使用foreach遍历,可以使用remove删除map节点
7.日期对象的操作由Calendar函数改为由LocalDate,LocalTime,Clock等函数操作
6.java创建线程池的4种方式及注意事项
1、newFiexedThreadPool(int Threads):创建固定数目线程的线程池。
2、newCachedThreadPool():创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
3、newSingleThreadExecutor()创建一个单线程化的Executor。
4、ewScheduledThreadPool(int corePoolSize)创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
看起来功能还是比较强大的,又用到了工厂模式、又有比较强的扩展性,重要的是用起来还比较方便,如:
ExecutorService executor = Executors.newFixedThreadPool(nThreads) ;
声明线程池时,注意要声明阻塞队列的长度,否则按默认长度会导致内存溢出
可以直接调用ThreadPoolExecutor来自定义线程池
========================额外小知识=======================
jar包运行会从Manifest里找main-class,没有没有这个属性要自己指定
springboot打包要用打包插件spring-boot-maven-plugin,会将main-class指定为
org.springframework.boot.loader.JarLauncher,用于调用加载类,调用内部tomcat
maven-surefire-plugin可以用来跳过mvn test