1.java基础知识
1.1冒泡排序
java中,如果不明确指定,整数型的默认类是int类型,带小数的默认是double类型;
class One{
public static void main(String []args){
int a[]=new int[]{1,4,7,2,5,8,9,6,3};
for(int b=0;b<a.length-1;b++){//表示遍数
for(int c=0;c<a.length-1;c++){
if(a[c]>a[c+1]){
int d=a[c];
a[c]=a[c+1];
a[c+1]=d;
}
}
}
System.out.println(Arrays.toString(a));
}
}
1.2九九乘法表
class two{
public static void main (String[]args){
int a=9;
for(int b=1;b<=a;b++){
System.out.println();
for(int c=1;c<=b;c++){
System.out.print(b+"*"+c+"="+b*c+" ");
}
}
}
}
jdk:是java软件开发的工具包
jre:是java软件的运行环境
1.3基本类型
整型:byte(1个字节) short(2个字节) int(4个字节) long(8个字节)
浮点型:float(4个字节) double(8个字节)
字符型:char(2个字节)
布尔型:boolean(1个字节)
java特性跨平台运行时把文件转化为2进制
1.4==和equals的区别
==表示的是值表示的是内存的地址
equals表示的是两个对象的各个字段的属性值是否相等
1.5string常用的API:
includes:字符串中是否包含某个字符 --用法str.includes()
substring:从字符串中截取某个字符串 —用法str.substring(int a, int b)
replace:把字符串中的某些或者某个字符替换为 --用户str.replace("","")
split:拆分–str.split("")
concat:将字符串拼接在在原字符串的后面 --str.concat("")
length:字符串长度
1.6类加载的过程
一般来说,我们把 Java 的类加载过程分为三个主要步骤:加载,连接,初始化,具体行为在 Java 虚拟机规范里有非常详细的定义。
首先是加载过程(Loading),它是 Java 将字节码数据从不同的数据源读取到 JVM 中,并映射为 JVM 认可的数据结构(Class 对象),这里的数据源可能是各种各样的形态,比如 jar 文件,class 文件,甚至是网络数据源等;如果输入数据不是 ClassFile 的结构,则会抛出 ClassFormatError。加载阶段是用户参与的阶段,我们可以自定义类加载器,去实现自己的类加载过程。
第二阶段是连接(Linking),这是核心的步骤,简单说是把原始的类定义信息平滑地转入 JVM 运行的过程中。这里可进一步细分成三个步骤:1,验证(Verification),这是虚拟机安全的重要保障,JVM 需要核验字节信息是符合 Java 虚拟机规范的,否则就被认为是 VerifyError,这样就防止了恶意信息或者不合规信息危害 JVM 的运行,验证阶段有可能触发更多 class 的加载。2,准备(Pereparation),创建类或者接口中的静态变量,并初始化静态变量的初始值。但这里的“初始化”和下面的显示初始化阶段是有区别的,侧重点在于分配所需要的内存空间,不会去执行更进一步的 JVM 指令。3,解析(Resolution),在这一步会将常量池中的符号引用(symbolic reference)替换为直接引用。在 Java 虚拟机规范中,详细介绍了类,接口,方法和字段等各方面的解析。
最后是初始化阶段(initialization),这一步真正去执行类初始化的代码逻辑,包括静态字段赋值的动作,以及执行类定义中的静态初始化块内的逻辑,编译器在编译阶段就会把这部分逻辑整理好,父类型的初始化逻辑优先于当前类型的逻辑。再来谈谈双亲委派模型,简单说就是当加载器(Class-Loader)试图加载某个类型的时候,除非父类加载器找不到相应类型,否则尽量将这个任务代理给当前加载器的父加载器去做。使用委派模型的目的是避免重复加载 Java 类型。
2.java中的集合
2.1 概述
英文名称Collection,是用来存放对象的数据结构。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。
数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。
List,Set都是继承至Collection接口,而Map为独立接口
1.List下有ArraysList,LinkedList
2.Set下有HashSet,TreeSet
3.Map下有Hash Map,TreeMap
2.2 List集合
有序列表,可存放重复元素
实现类:
1.ArrayList:底层数据结构是和数组,查询快,增删慢,线程不安全
2.LinkedList:底层的数据结果是双向链表,增删快,查询慢,线程不安全
2.3 Set集合
无需列表。不能重复,没有下标
实现类
1.HashSet:底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
依赖两个方法:hashCode()和equals()
2.TreeSet:底层数据结构是红黑树。(唯一,有序)
如何保证元素排序的呢?
自然排序
比较器排序
如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
2.4Map集合
Map<K,V> 可以根据键,提取对应的值,
键不允许重复,如果重复会被覆盖
实现类:
1.HashMap:底层是以数组方式进行存储。将key-value对作为数组中的一个元素进行存储。
2.TreeMap:有序存储K-V键值对,通过红黑树实现
3.四大元注解
1.@Target(ElementType.TYPE) 标识注解对谁有效. 该注解表示对类有效.
2.@Retention(RetentionPolicy.RUNTIME) 标识注解的有效期 在运行时有效. 一般都写runtime
3.@Documented 动态生成文档文件.
4.@Inherited 是否允许子注解继承该注解.
数据库连接池
JDBC
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源
泛型
? - 表示不确定的java类型
通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期
代码通用性更强,后面有案例
泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的。
4 进程
4.1 概念
就是正在运行的程序。也就是代表了程序锁占用的内存区域。
4.2 特点
独立性:进程是系统中独立存在的实体,它可以拥有自己的独立的资源,每一个进程都拥有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间。
动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念,进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。
并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响。
4.3线程生命周期,总共有五种状态:
1) 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
2) 就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
3) 运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
4) 阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态;
5) 根据阻塞产生的原因不同,阻塞状态又可以分为三种:
a) 等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
b) 同步阻塞:线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
c) 其他阻塞:通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
6) 死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
4.4同步锁
4.5 乐观锁
4.5 悲观锁
5 数据库的事务
1.原子性:事务一旦提交,要么成功,要么失败
2.一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态;
3.持久性:事务提交,永久保存
4.隔离性:多个事务并发执行时,事务的内部与其他事务是隔离的,并发的各个事务互补干扰;
6 Spring MVC
7 spring
7.1 IOC
7.2 AOP
切面=通知方法(5种)+切入点表达式(4种)
动态代理:jdk动态代理
CGLIB动态代理
8 springboot
springboot即开箱即用,添加相关依赖,使用对应的注解就可以替代繁琐的xml
7.1@Controller和@RestController的区别
@Controller类的方法可以直接通过 返回string跳转jsp html等模板对象
@RestController类的方法String、Object、Json等实体对象,不能跳转到模版页面。
@RestController相当于@ResponseBody + @Controller。
8.2yml与properties优先级
yml:K: (空格)V 表示一组键值对(空格必须有)
properties:所有相同的前缀每一次都需要书写。
在properties文件中是以”.”进行分割的, 在.yml中是用”:”进行分割;
9.缓存(redis)问题
9.1 五大基本类型:String,Set,Hash,List,SortSet
问题出发点:
由于缓存失效,然而大量的用户请求,直接访问数据库服务器,导致负载过高,从而会引起整体的宕机的风险!!!
9.1.1缓存穿透
说明: 用户频繁访问数据库中不存在的数据,可能出现缓存穿透的现象.如果该操作是高并发操作,则可能直接威胁数据库服务器.
解决方案:
1.采用IP限流的方式 降低用户访问服务器次数. IP动态代理(1分钟变一次)
2.微服务的处理方式: 利用断路器返回执行的业务数据即可不执行数据库操作 从而保护了数据库.
3.微服务处理方式: API网关设计. 不允许做非法操作
9.1.2缓存击穿
说明: 由于redis中某个热点数据由于超时/删除等操作造成数据失效.同时用户高并发访问该数据,则可能导致数据库宕机.该操作称之为 缓存击穿.
解决方案: 可以采用多级缓存的设计. 同时数据的超时时间采用随机数的方式.
9.1.3 缓存雪崩
说明: 由于redis内存数据大量失效.导致用户的访问命中率太低.大量的用户直接访问数据库,可能导致数据库服务器宕机. 这种现象称之为缓存雪崩.
解决:
1.采用多级缓存.
2.设定不同的超时时间
3.禁止执行 flushAll等敏感操作.
9.2缓存的持久化
9.2.1RDB持久化
是在某个定期的时间间隔进行快照持久化,效率高,但容易丢失
9.2.2AOF持久化
是手动开启,记录是实时进行的,文件比较大,效率低