建一个类似亨物说网站建设费用,百度app内打开,中学生做的网站有哪些,wordpress更改域名网页走失引用介绍
1.线程安全不安全的概念
线程安全: 指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。
线程不安全: 是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏…引用介绍
1.线程安全不安全的概念
线程安全: 指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。
线程不安全: 是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
2.结构化数据的概念
结构化数据:有规律的一类数据;例如:人的信息,动物信息,考试信息 非结构化数据:海量的不具备任何共同特性的数据集合;例如:网页,日志;图片
3.关系型和非关系型数据库的概念 关系型数据库:体现不同类结构化数据之间的关系的数据,例如ORACLE mysql非关系型数据库:存储的是非结构化的海量数据;无法体现数据的关系;例如 mongoDB red
4.什么是序列化
序列化的定义
**序列化**把对象转化为可传输的字节序列过程称为序列化。
**反序列化**把字节序列还原为对象的过程称为反序列化。
列化最终的目的是为了对象可以跨平台存储和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO而我们的IO支持的数据格式就是字节数组。
https://zhuanlan.zhihu.com/p/40462507 Java基础篇
1.Java核心思想
抽象、继承、封装、多态
2. Java语言的特点
①面向对象使用计算机模拟现实世界Java最重要的特性让程序耦合度更低内聚性更高
②简单易学、有丰富的类库
③跨平台JVM是Java跨平台使用的根本
④支持多线程
⑤安全可靠
3. Java运行机制
①编译型
源码–编译器–编译–机器码编译一次运行效率高
②解释型
源码–解释器–逐渐解释运行跨平台
先编译后解释源码–编译–字节码class文件)–解释器–逐渐解释运行
③Java运行环境
JVMJava虚拟机:屏蔽底层操作系统差异
Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域
JREJava运行环境也叫java平台 JVM解释器
JDK是程序开发者用来来编译、调试java程序用的开发工具包。JDK的工具也是Java程序也需要JRE才能运行 JRE编译器类库工具包Java开发工具包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SXhjEpJN-1663727038774)(C:\Users\wangy\AppData\Roaming\Typora\typora-user-images\image-20220806130750712.png)]
常见的DOS命令
切换盘符例如 D:
进入目录cd目录名
返回上一级目录cd …
Java最小组成单位是类使用class定义类
4. 数据类型
对象类型引用类型有无数种
基础类型 基础类型又分为4类共有8种1代表1个字节2代表2个字节
1、整数型 byte [1]、short[2] 、int[4] 、long[8]
2、浮点型 float [4]、 double[8]
3、字符型 char[2]存放单个字符如’a’、‘男’单个字母占1个字节单个汉字占2个字节
4、布尔型 boolean[1]存放true、false
八种基本类型
类型字节大小取值范围封装器类说明byte1字节-128~127Byte字符型数据存储在内存中的最原始形态short2字节-32768~32767Short短整型int4字节-2147483648~2147483647Integer整型long8字节-9223372036854775808~223372036854775807Long长整型float4字节-±3.40282347E38F有效位数为6-7位Float浮点型用于存储单精度数字double8字节±1.79769313486231570E308有效位数为15位Double双精度型用于存储双精度数字默认声明的小数char2字节分为两种一种是无符号整型数据类型unsigned char另一种是有符号整型数据类型signed charCharacter字符型用于存储字符以 Unicode 编码方式boolean1字节布尔类型只有俩个值false和true用来逻辑判断Boolean布尔型用于存储真值或假值
4. 逻辑运算符
与的比较
共同点两个条件都为true结果才是true。
不同点
短路与如果第一个条件为false则第二个条件就不会再判断最终结果为false效率高。所以实际开发中用的较多逻辑与不管第一个条件是否为false第二个条件都要判断效率低。
逻辑或 I” 和 “短路或 II
共同点两个条件都为false结果才是false。
不同点
短路或II如果第一个条件为true则第二个条件就不会再判断最终结果为true。效率高。逻辑或I不管第一个条件是否为true第二个条件都要判断效率低。
6. 条件分支和循环结构
1. 条件分支
①if和if else
②switch
2. 循环结构
①while和do while
②for循环
7. 函数
函数三要素返回值类型函数名形参函数内部有效的的局部变量多个形参用逗号隔开
函数是一组代码完成特定的任务
函数的作用
①避免冗余代码
②提高程序的可维护性
③提高程序的灵活性
④提高程序的重用性
8. 数组
数组的概念一次性定义多个同类型的变量而且数组空间在内存中必然是连续的数组的长度是固定的要扩充必须创建新数组把原先的数组copy到新数组中。
①一维数组
如
// 分配数组长度
int[] a new int[3];
// 数组长度的显式初始化
int[] a {1,2,3};
// 数组扩容有自带的方法
java.util.Arrays.copyOf(数组名数组长度如a.length*2)②二维数组 // 分配数组长度
// [4]行数 [3]列数
int[][] anew int[4][3]列数;
String[][] bnew String[4][3];
// 数组长度的显式初始化
int[][] a{{1,2,3,4},{4,5,6,7},{8,9,10,11}}9. 面向对象内容
编程思想需求–建立思路–目标代码自顶而下逐步求精
面向对象的关键各司其职、弱耦合性、可扩展性
①方法的重载(OverLoad)与方法的覆盖(Override)
重载 OverLoad
方法名相同形参不同
1.参数个数不同
2.参数类型不同
3.参数类型排列不同
4.重载不一定在自身的类中继承也可以
覆盖Override
1.参数名称相同参数值相同
②构造方法的特点
1.没有返回值
2.方法名必须和类名相同
3.不允许手工调用在对象构造过程中自动调用一次
如果在一个类中没有任何构造方法系统会默认一个无参的构造方法
③对象创建的过程
1.分配空间所有实际变量被赋默认值
2.初始化属性所有的实例变量被赋初始值
3.调用构造方法实例变量常常被三次赋值
④类加载的时机何时发生类加载
1.创建类的对象
2.访问类的静态成员
3.加载子类引发加载父类
4.反向声明引用不会发生类加载
10. 集合
Java 集合可分为 Collection 和 Map 两种体系 Collection(所有元素必须是对象类型) List元素有序有下标元素内容可以重复 ArrayList 基于数组实现的是线程不安全的查询快因为是以数组为下标查询增删慢是因为ArrayList是数组所以在其中进行增删操作时会对操作点之后所有数据的下标索引造成影响需要进行数据的移动Vertor基于数组实现线程安全但是效率慢LinkedList基于链表实现的线程不安全增删快查询慢因为LinkedList是线性的数据存储方式所以需要移动指针从前往后依次查找比ArrayList 更占内存 常用方法 add,remove,get,indexof,set,subList Set元素无序无下标元素内容不可以重复初始容量为16负载因子0.75倍扩容量增加1倍 HashSet储存唯一元素为空值不保持插入顺序线程不安全内容不可以重复LinkedHashSet:数组加链表实现可以保证元素的获取顺序和添加的顺序一致如果要保证自定义元素类型不重复必须重写hashcode和equals方法TreeSet红黑树可以根据元素内容自动进行升序排列有序的且没有重复元素的集合自然排序或者根据提供的Comparator进行排序TreeSet是基于TreeMap实现的 常用方法 add,remove,contains,size,toArray Map(双列数据保存具有映射关系“key-value对”的集合),key和value都是泛型的所以Map的key和value可以任意类型的 HashMap 线程不安全keyvalue存储key唯一允许空值但是key只能有一个空值LinkdHashMap继承自HashMap的多线程不安全的、用于存储K、V键值对的有序集合类在HashMap基础上对存储的元素节点添加了前后指针、额外维护了一个双向链表维持顺序。由于增加了前后指针当进行Put、Get、Replace等操作时会有维护双向链表的额外开销。(要求输入顺序和输出顺序相同,是有序的)TreeMapTreeMap是一个有序的key-value集合它内部是通过红-黑树实现的它支持序列化增删改查的平均和最差时间复杂度均为O最大特点时Key有序实现了sortMap接口能够把保存的记录按照键排序(默认升序)也可以指定排序比较器遍历时得到的数据是排过序的Hashtable: Key不可为空、多线程安全、无序。底层采用数组 链表 的结构
11.HashMap如何用对象作为key
key对象的要求
1.该对象不可变
2.重写equals方法
3.重写hashCode()方法
使用HashMap的key作为对象的时候不满足上述条件会导致用key取到的对象为null,地址变了不能保证hash值和equals结果还是一样。所以取不到对应的value。 1 两个对象要equals()true,那么该两个对象指向的一定是同一块内存空间。2 HashMap在比对Map中是否存在key是就是使用的equals方法3 HashMap在向Map中增加Key时是通过hashCode()方法计算散列值,将其插入到指定的位置4 结合2如果两个对象一样所以只要对应的属性值一样。那么就可以equals等于true,不需要他们指向同一块内存空间,所以必须重写对 象的equals()方法5 结合hashCode的常规协定重写了equals方法最好重写hashCode方法6 如果对象改变了那么上述两个方法结果就改变了所以一般key对象的不可变12.HashMap的特点
1 非线程安全 (注如果需要满足线程安全可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力或者使用ConcurrentHashMap)
2有很快的访问速度但遍历顺序却是不确定的
3HashMap最多只允许一条记录的键为null但是允许多条记录的值为nulll
13.HashMap的实现原理
①实现原理
1.HashMap基于hashing原理通过put(key,value)和get(key)方法存储和获取对象。 2.当存储对象时将键值传递给put(keyvalue)方法时它调用键对象的key的hashCode()方法来计算hashCode,然后找到bucket位 置来存储值对象value 3.当获取对象时也是先计算key的hashCode,找到数组种对应位置的bucket位置然后通过key的equals()方法找到正确的键值对key- value,然后返回值对象value 4.HashMap使用链表来解决碰撞问题当发生碰撞了对象会将存储在链表的下一个节点中。Hash每个链表节点中存储键值对key- value对象也就是当两个不同的键对象key 的hashcode相同时它们会存储在同一个bucket位置的链表(JDK8链表长度大于8变红黑树)中取数据可通过键对象key的equas()方 法来找到正确的键值对key-value
②HashMap的底层数据结构
jdk1.8之前 HashMap的实现是数组链表它之所以查询速度快主要是因为它是通过key计算hashCode来决定一维数组中存储的位置而增删速度靠的是链表保证 jdk1.8中 用数组链表红黑树的结构来优化链表长度大于8同时满足HashMap中元素个数大于64则变红黑树长度小于6变回链表
③什么是hash表
散列表(Hash Table,也叫哈希表)是根据关键码值(key,value)而直接访问的数据结构也就是说它通过关键码值映射到表中一个位置来访问记录以加快查找的速度。 这个映射函数叫做散列函数存放记录的数据叫做散列表。
hash表里面可以存储元素的位置称为桶(bucket)
④什么是Hash冲突
不同的key产生产生相同的Hash地址 解决方案 1.开放地址法:探测序列查找一个空的单元插入。 方法有线性探测、再平方、伪随机 2.链地址法对于相同的值使用链表进行连接。使用数组存储的每一个链表。HashMap中使用方案 3.公共溢出区法建立一个特殊的存储空间专门存放冲突的数据。此方法适于数据和冲突较少的情况 4.再散列法准备若干个hash函数如果使用第一个hash函数发生了冲突就是使用第二个hash函数依次类推
14.equals与 的区别
答 比较的是栈内存中存放对象的内存地址是否相同equals比较的是内容是否相同如果是比较数字的话可以用比较内容用equals
15String常用的方法
isEmpty()equals(equalsIgnoreCase()hashCode()indexOf()substring()concat()replace()contains()split()trim()toString()format()valueOf()
public boolean isEmpty() {return value.length 0;
}
public boolean equals(Object anObject) {if (this anObject) {return true;}if (anObject instanceof String) {String anotherString (String)anObject;int n value.length;if (n anotherString.value.length) {char v1[] value;char v2[] anotherString.value;int i 0;while (n-- ! 0) {if (v1[i] ! v2[i])return false;i;}return true;}}return false;}public boolean equalsIgnoreCase(String anotherString) {return (this anotherString) ? true: (anotherString ! null) (anotherString.value.length value.length) regionMatches(true, 0, anotherString, 0, value.length);}//按字典顺序比较两个字符串//首先取出两个字符串的长度比较较小的长度内两者是否相等。//若不相等则直接返回该位置字符的ASCII码相减后的值。//若各位置都相等则将两个字符串长度的差值返回。public int compareTo(String anotherString) {int len1 value.length;int len2 anotherString.value.length;int lim Math.min(len1, len2);char v1[] value;char v2[] anotherString.value;int k 0;while (k lim) {char c1 v1[k];char c2 v2[k];if (c1 ! c2) {return c1 - c2;}k;}return len1 - len2;}
public int hashCode() {int h hash;if (h 0 value.length 0) {char val[] value;for (int i 0; i value.length; i) {h 31 * h val[i];}hash h;}return h;}public int indexOf(int ch) {return indexOf(ch, 0);}public String substring(int beginIndex, int endIndex) {if (beginIndex 0) {throw new StringIndexOutOfBoundsException(beginIndex);}if (endIndex value.length) {throw new StringIndexOutOfBoundsException(endIndex);}int subLen endIndex - beginIndex;if (subLen 0) {throw new StringIndexOutOfBoundsException(subLen);}return ((beginIndex 0) (endIndex value.length)) ? this: new String(value, beginIndex, subLen);}public String concat(String str) {if (str.isEmpty()) {return this;}int len value.length;int otherLen str.length();char buf[] Arrays.copyOf(value, len otherLen);str.getChars(buf, len);return new String(buf, true);}
public String replace(char oldChar, char newChar) {if (oldChar ! newChar) {int len value.length;int i -1;char[] val value; /* avoid getfield opcode */while (i len) {if (val[i] oldChar) {break;}}if (i len) {char buf[] new char[len];for (int j 0; j i; j) {buf[j] val[j];}while (i len) {char c val[i];buf[i] (c oldChar) ? newChar : c;i;}return new String(buf, true);}}return this;}
public boolean contains(CharSequence s) {return indexOf(s.toString()) -1;}public String replace(CharSequence target, CharSequence replacement) {return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));}public String[] split(String regex, int limit) {}public static String join(CharSequence delimiter, CharSequence... elements) {Objects.requireNonNull(delimiter);Objects.requireNonNull(elements);// Number of elements not likely worth Arrays.stream overhead.StringJoiner joiner new StringJoiner(delimiter);for (CharSequence cs: elements) {joiner.add(cs);}return joiner.toString();}public String trim() {int len value.length;int st 0;char[] val value; /* avoid getfield opcode */while ((st len) (val[st] )) {st;}while ((st len) (val[len - 1] )) {len--;}return ((st 0) || (len value.length)) ? substring(st, len) : this;
}
public String toString() {return this;}
public static String format(String format, Object... args) {return new Formatter().format(format, args).toString();
}
public static String valueOf(Object obj) {return (obj null) ? null : obj.toString();
}16.重写和重载的区别
答重写 1.发生在父类与子类之间 2.方法名参数列表返回类型除过子类中方法的返回类型是父类中返回类型的子类必须相同 3.访问修饰符的限制一定要大于被重写方法的访问修饰符publicprotecteddefaultprivate) 4.重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
重载 1.重载Overload是一个类中多态性的一种表现 2.重载要求同名方法的参数列表不同(参数类型参数个数甚至是参数顺序) 3.重载的时候返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准
17抽象类和接口的区别
1.抽象类中可以有构造方法接口中不能有构造方法
2.抽象类中可以有普通成员变量接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法接口中的所有方法都必须是抽象的不能有非抽象的普通方法
4.抽象类中可以包含静态方法接口中不能包含静态方法
5.抽象类中的抽象方法的访问类型可以是public、protected和(默认类型default)但接口中的方法只能是public类型的并且默认为public static final类型
18.String Stringbuffer Stringbuilder 区别
String是只读字符串被final修饰一旦定义无法增删改每次对String操作都会产生一个新的String对象它是不可变的是定长的适用于少量字符串拼接如果使用大量字符串拼接会造成空间浪费 Stringbuffer是线程安全的被同步锁给修饰 StringBuild没有被同步锁修饰是线程不安全的适用于单线程下字符缓冲区进行大量操作的情况单线程下线程安全多线程下线程不安全 StringBuffer和StringBuilder他们两都继承了AbstractStringBuilder抽象类
19.Collection包结构与Collections的区别
Collection是集合类的上级接口子接口有 Set、List Collections是集合类的一个帮助类 它包含有各种有关集合操作的静态多态方法用于实现对各种 集合的搜索、排序、线程安全化等操作。此类不能实例化就像一个工具类服务于Java的Collection框架。
20.Java创建对象有几种方式
java中提供了以下四种创建对象的方式: new创建新对象 通过反射机制 采用clone机制 通过序列化机制
21.final有哪些用法
被final修饰的类不可被继承 被final修饰的方法不可以被重写 被final修饰的变量不可以被改变.如果修饰引用,那么表示引用不可变,引用指向的内容可变. 被final修饰的方法,JVM会尝试将其内联,以提高运行效率 被final修饰的常量,在编译阶段会存入常量池中.
22.try catch finallytry里有returnfinally还执行么
执行并且finally的执行早于try里面的return 结论 1、不管有木有出现异常finally块中代码都会执行 2、当try和catch中有return时finally仍然会执行 3、finally是在return后面的表达式运算后执行的此时并没有返回运算后的值而是先把要返回的 值保存起来不管finally中的代码怎么样返回的值都不会改变任然是之前保存的值所以函数 返回值是在finally执行前确定的 4、finally中最好不要包含return否则程序会提前退出返回值不是try或catch中保存的返回值。
23.简述线程、程序、进程的基本概念。以及他们之间关系是什么?
进程线程
线程与进程相似但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源所以系统在产生一个 线程或是在各个线程之间作切换工作时负担要比进程小得多也正因为如此线程也被称为轻量级进程。
程序是含有指令和数据的文件被存储在磁盘或其他的数据存储设备中也就是说程序是静态的码。进程是程序的一次执行过程是系统运行程序的基本单位因此进程是动态的。系统运行一个程序即是一个进程从创建运行到消亡的过程。简单来说一个进程就是一个执行中的程序它在计算机中一个指令接着一个指令地执行着同时每个进程还占有某些系统资源如 CPU 时间内存空
间文件输入输出设备的使用权等等。换句话说当程序在执行时将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的而各线程则不一定因为同一进程中的线程极有可能会相互影响。从另一角度来说进程属于操作系统的范畴
主要是同一段时间内可以同时执行一个以上的程序而线程则是在同一程序内几乎同时执行一个以上的程序段24.说说List,Set,Map三者的区别
List(有序) 元素有序有下标元素内容可以重复 Set(注重独一无二的性质): 元素无序无下标元素内容不可以重复初始容量为16负载因子0.75倍扩容量增加1倍 Map(用Key来搜索的专家): 使用键值对存储。Key不能重复典型的Key是String类型但也可以是任何对象。
25.反射的实现方式
1Class.forName(“类的路径”)
2类名.class
3对象名.getClass()
4基本类型的包装类可以调用包装类的Type属性来获得该包装类的Class对象
26.请简单说一下集合
Java 集合可分为 Collection 和 Map 两种体系 ①Collection有子接口List和Set, List常用的实现类有ArrayList,LinkedList,Vector。 ArrayList:数组实现查询快增删慢查询快因为是根据下标进行查询增删慢是因为每次删除之后会对操作点之后所有数据的下标索引造成影响需要进行数据的移动 LinkedList链表实现的线程不安全增删快查询慢因为LinkedList是线性的数据存储方式所以需要移动指针从前往后依次查找比ArrayList 更占内存 Vertor基于数组实现线程安全但是效率慢 常用的方法有add,remove,get,set等方法 ②Map常用的实现类有HashMap、LinkdHashMap、TreeMap、HashTable常用的方法有add,remove,size,contains等方法 HashMap: 1特点 1.key-value存储形式存在的存取是无序的它是线程不安全的 2.键和值都可以为null但是键位置只能是一个null 3.键位置是唯一的 4.JDK1.8之前数组链表 JDK1.8之后数组链表红黑树 5.阈值8且数组长度64才将链表转换为红黑树目的是为了更高效的查询 2默认16 1. 使用位与运算计算效率高 2. 设置容量为2的幂指数避免了hash碰撞产生链表使得结果可以均匀分布3. 提高了查询效率LinkdHashMap1继承自HashMap的多线程不安全的、用于存储K、V键值对的有序集合类在HashMap基础上对存储的元素节点添加了前后指针、额外维护了一个双向链表维持顺序。由于增加了前后指针当进行Put、Get、Replace等操作时会有维护双向链表的额外开销。使用迭代器遍历时比HM要快。使用场景是当设定为按访问顺序存储时适合做LRU缓存 TreeMap1TreeMap是一个有序的key-value集合它内部是通过红-黑树实现的它支持序列化增删改查的平均和最差时间复杂度均为O最大特点时Key有序HashTable1Key不可为空、多线程安全、无序。底层采用数组 链表 的结构27.hastMap和hashtable的区别
1、两者父类不同HashMap是继承自AbstractMap类而Hashtable是继承自Dictionarydɪkʃənri类。不过它们都实现了同时实现了map、Cloneable可复制、Serializable可序列化这三个接口。 2、对外提供的接口不同Hashtable比HashMap多提供了elments() 和contains() 两个方法。 elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。 contains()方法判断该Hashtable是否包含传入的value。它的作用与containsValue()一致。事实上contansValue() 就只是调用了一下contains() 方法。 3、对null的支持不同 Hashtablekey和value都不能为null。 int[] a new int[4];//推介使用int[] 这种方式初始化 int c[] {23,43,56,78};//长度4索引范围[0,3] HashMapkey可以为null但是这样的key只能有一个因为必须保证key的唯一性可以有多个key 值对应的value为null。 4、安全性不同 HashMap是线程不安全的在多线程并发的环境下可能会产生死锁等问题因此需要开发人员自己处理多线程的安全问题。 Hashtable是线程安全的它的每个方法上都有synchronized 关键字因此可直接用于多线程中。 虽然HashMap是线程不安全的但是它的效率远远高于Hashtable这样设计是合理的因为大部分的 使用场景都是单线程。当需要多线程操作的时候可以使用线程安全的ConcurrentHashMap。 ConcurrentHashMap虽然也是线程安全的但是它的效率比Hashtable要高好多倍。因为 ConcurrentHashMap使用了分段锁并不对整个数据进行锁定。 5、初始容量大小和每次扩充容量大小不同 6、计算hash值的方法不同
28.线程安全的map,SynchronizedMap和ConcurrentHashMap有什么区别
SynchronizedMap()和Hashtable一样实现上在调用map所有方法时都对整个map进行同步。而ConcurrentHashMap的实现却更加精细它对map中的所有桶加了锁。所以只要有一个线程访问 map其他线程就无法进入map而如果一个线程在访问ConcurrentHashMap某个桶时其他线程仍然可以对map执行某些操作。 所以ConcurrentHashMap在性能以及安全性方面明显比Collections.synchronizedMap()更加有优势。同时同步操作精确控制到桶这样即使在遍历map时如果其他线程试图对map进行数据修 改也不会抛出ConcurrentModificationException。
29.高并发的map之ConcurrentHashMap
它的数据结构和HashMap一样采用数组链表红黑树默认分为16段每次操作都会对桶进行加锁支持任意线程的并发读写它使用可重入锁ReentrantLock进行加锁
30arrayList和LinkedList的区别
ArrayList:数组实现查询快增删慢查询快因为是根据下标进行查询增删慢是因为每次删除之后会对操作点之后所有数据的下标索引造成影响需要进行数据的移动 LinkedList链表实现的线程不安全增删快查询慢因为LinkedList是线性的数据存储方式所以需要移动指针从前往后依次查找比ArrayList 更占内存
31.都有哪几种锁
https://blog.csdn.net/qq_39380737/article/details/105081827
Lock,读写锁重入锁轻量级ReentrantLock和重量级synchronized同步锁悲观锁乐观锁 读写锁读-读能共存读-写不能共存写-写不能共存适用场景对一些共享资源的读和写操作且写操作没有读操作那么频繁。在没有写操作的时候两个线程同时读一个资源没有任何问题所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源就不应该再有其它线程对该资源进行读或写 乐观锁总是认为不会产生并发问题每次去取数据的时候总认为不会有其他线程对数据进行修改因此不会上锁但是在更新时会判断其他线程在这之前有没有对数据进行修改一般会使用版本号机制或CAS操作实现。 悲观锁总是假设最坏的情况每次取数据时都认为其他线程会修改所以都会加锁读锁、写锁、行锁等当其他线程想要访问数据时都需要阻塞挂起。可以依靠数据库实现如行锁、读锁和写锁等都是在操作之前加锁在Java中synchronized的思想也是悲观锁
**同步锁**具有互斥性
mysql
表级锁开销小加锁快不会出现死锁锁定粒度大发生锁冲突的概率最高并发度最低表锁就是一锁锁一整张表在表被锁定期间其他事务不能对该表进行操作必须等当前表的锁被释放后才能进行操作。表锁响应的是非索引字段即全表扫描全表扫描时锁定整张表sql语句可以通过执行计划看出扫描了多少条记录。 处理非索引字段时通常是锁表行级锁开销大加锁慢会出现死锁锁定粒度最小发生锁冲突的概率最低并发度也最高行级锁在使用的时候并不是直接锁掉这行记录,而是锁索引 如果一条sql用到了主键索引(mysql主键自带索引),mysql会锁住主键索引; 如果一条sql操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引.页面锁开销和加锁时间界于表锁和行锁之间会出现死锁锁定粒度界于表锁和行锁之间并发度一般共享锁select * from tableName where … lock in share more排他锁select * from tableName where … for update
加锁的方式自动加锁。对于UPDATE、DELETE和INSERT语句InnoDB会自动给涉及数据集加排他锁对于普通SELECT语句InnoDB不会加任何锁当然我们也可以显示的加锁
共享锁select * from tableName where … lock in share more
排他锁select * from tableName where … for update
32单例 懒汉式和饿汉式的区别
饿汉式天生就是线程安全的可以直接用于多线程而不会出现问题 懒汉式本身是非线程安全的
饿汉式
优点
饿汉式单例是最简单的一种单例形式它没有添加任何的锁执行效率最高线程安全
缺点
某些情况下造成内存浪费因为对象未被使用的情况下就会被初始化如果一个项目中的类多达上千个在项目启动的时候便开始初始化可能并不是我们想要的。
public class SingletonEH {/***饿汉式*是否 Lazy 初始化否*是否多线程安全是*实现难度易*描述这种方式比较常用但容易产生垃圾对象。*优点没有加锁执行效率会提高。*缺点类加载时就初始化浪费内存。*它基于 classloder 机制避免了多线程的同步问题* 不过instance 在类装载时就实例化虽然导致类装载的原因有很多种* 在单例模式中大多数都是调用 getInstance 方法* 但是也不能确定有其他的方式或者其他的静态方法导致类装载* 这时候初始化 instance 显然没有达到 lazy loading 的效果。*/private static SingletonEH instance new SingletonEH();private SingletonEH (){}public static SingletonEH getInstance() {System.out.println(instance:instance);System.out.println(加载饿汉式....);return instance;}
}懒汉式
public class SingletonLH {/***懒汉式*是否 Lazy 初始化是*是否多线程安全否*实现难度易*描述这种方式是最基本的实现方式这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized所以严格意义上它并不算单例模式。*这种方式 lazy loading 很明显不要求线程安全在多线程不能正常工作。*/private static SingletonLH instance;private SingletonLH (){}public static SingletonLH getInstance() {if (instance null) {instance new SingletonLH();}return instance;}}双重检查锁
既能兼顾线程安全又能提升程序性能呢有这就是双重检查锁
public class SingletonLH {/***双重检查锁*需要添加 volatile 关键字*/// 需要添加 volatile 关键字private volatile static SingletonLH instance;private SingletonLH (){}public static SingletonLH getInstance() {//一重检查:检查实例如果不存在进入同步区块if (instance null) {synchronized (LazyDoubleCheck.class) {//双重检查: 进入同步区块后再检查一次如果仍然是null才创建实例if (instance null) {instance new SingletonLH();}}}return instance;}}https://blog.csdn.net/weixin_42208686/article/details/105078021
https://zhuanlan.zhihu.com/p/426672787
33.线程创建的几种方式
①继承Thread类创建线程类 ②通过Runnable接口创建线程类 ③实现Callable接口通过FutureTask包装器来创建Thread线程 ④通过线程池来创建线程
34ThreadLocal 的作用以及适用场景以及底层实现
ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单更方便且结果程序拥有更高的并发性 订单处理包含一系列操作减少库存量、增加一条流水台账、修改总账这几个操作要在同一个 事务中完成通常也即同一个线程中进行处理如果累加公司应收款的操作失败了则应该把前面 的操作回滚否则提交所有操作这要求这些操作使用相同的数据库连接对象而这些操作的代码 分别位于不同的模块类中 1、ThreadLocal类用于存储以线程为作用域的数据线程之间数据隔离。 2、ThreadLocalMap类是ThreadLocal的静态内部类通过操作Entry来存储数据。3、Thread类比较常用线程类内部维持一个ThreadLocalMap类实例threadLocals。35get和post的区别
①Get是用来从服务器上获得数据而Post是用来向服务器上传递数据 ②get拼接参数post是封装了对象 ③get请求是可以缓存的post请求不可以缓存 ④get一般传输数据大小不超过2k-4k根据浏览器不同限制不一样但相差不大post请求传输数据的大小根据php.ini 配置文件设定也可以无限大
36cookie session区别
1 作用范围不同Cookie 保存在客户端浏览器Session 保存在服务器端。
2 存取方式的不同Cookie 只能保存 ASCIISession 可以存任意数据类型一般情况下我们可以在 Session 中保持一些常用变量信息比如说 UserId 等。
3 有效期不同Cookie 可设置为长时间保持比如我们经常使用的默认登录功能Session 一般失效时间较短客户端关闭或者 Session 超时都会失效。
4 隐私策略不同Cookie 存储在客户端比较容易遭到不法获取早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取Session 存储在服务端安全性相对 Cookie 要好一些。
5 存储大小不同 单个 Cookie 保存的数据不能超过 4KSession 可存储数据远高于 Cookie。37类加载过程
1、加载 2、验证 3、准备 4、解析 5、 初始化 6、使用 7、卸载。
38Thread 类中的start() 和 run() 方法有什么区别
start()方法被用来启动新创建的线程而且start()内部调用了run()方法这和直接调用run()方法的效果 不一样。当你调用run()方法的时候只会是在原来的线程中调用没有新的线程启动start()方法才会 启动新线程。
39http1.1和1.0区别
1.可扩展性 2 缓存 3 带宽优化 4 长连接 5 消息传递 6 Host头域 7 错误提示 8 内容协商
40 网络传输七层协议
https://blog.csdn.net/aaqingying/article/details/116853873
1 物理层 2 数据链路层 3 网络层 4 传输层 5 会话层 6 表示层 7 应用层
物理层 ----数据链路层----网络层----传输层----表示层 ----应用层
41 io的用法
InputStreamReader:将一个字节的输入流转为字符的输入流 OutputStreamWriter:将一个字符的输出路转为字节的输出流
42jdk1.8的新特性
一、 Lambda 表达式 使用Lambda必须有接口并且接口中有且仅有一个抽象方法。 只有当接口中的抽象方法存在且唯一时才可以使用Lambda但排除接口默认方法以及声明中覆盖Object的公开方法。 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型才能使用Lambda作为该接口的实例。 二、 方法引用 三、函数式接口有且仅有一个抽象方法的接口 如修饰符 interface 接口名称 { public abstract 返回值类型 方法名称(可选参数信息); // 其他非抽象方法内容 } 四、 接口允许定义默认方法和静态方法 五、Stream API 六、日期/时间类改进 七、Optional 类 八、 Java8 Base64 实现
43hashMap的实现原理:
数组链表实现的 主干是一个Entry数组Entry是hashMap的基本组成单元每一个Entry包含一个key-value键值对
44juccountdownlatch并发包
CountDownLatch是JDK提供的一个同步工具它可以让一个或多个线程等待一直等到其他线程中执行完成一组操作。可以用作线程同步 方法有countDown方法、await方法等
45单元测试中的断言
作用是用于对程序进行调试的对于执行结构的判断而不是对于业务流程的判断。相当于一个if ()语句如果满足断言的执行程序如果不满足则抛错误 使用情形断言只适用复杂的调式过程。如果不复杂完全可以用log或者debug代替
46时间复杂度
常见复杂度量级
分类记作常量阶O(1)对数阶O(logn)线性阶O(n)线性对数阶O(nlogn)n方阶O(nⁿ)指数阶O(2ⁿ)阶乘阶O(n!)
https://blog.csdn.net/qq_41297896/article/details/104223612
47:TCP的三次握手
TCP三次握手是浏览器和服务器建立连接的方式目的是为了使二者能够建立连接便于后续的数据交互传输。 第一次握手浏览器向服务器发起建立连接的请求 第二次握手服务器告诉浏览器我同意你的连接请求同时我也向你发起建立连接的请求 第三次握手浏览器也告诉服务器我同意建立连接。 至此双方都知道对方同意建立连接并准备好了进行数据传输也知道对方知道自己的情况。接下来就可以传输数据了
48java中的nio
NIO (New lO)也有人称之为java non-blocking lO是从Java 1.4版本开始引入的一个新的IO API可以替代标准的Java lO API。NIO与原来的IO有同样的作用和目的但是使用的方式完全不同NIO支持面向缓冲区的、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作。NIO可以理解为非阻塞IO,传统的IO的read和write只能阻塞执行线程在读写IO期间不能干其他事情比如调用socket.read()时如果服务器一直没有数据传输过来线程就一直阻塞而NIO中可以配置socket为非阻塞模式。
NIO相关类都被放在java.nio包及子包下并且对原java.io包中的很多类进行改写。
NIO有三大核心部分:Channel(通道)Buffer(缓冲区), Selector(选择器)
Java NlO的非阻塞模式使一个线程从某通道发送请求或者读取数据但是它仅能得到目前可用的数据如果目前没有数据可用时就什么都不会获取而不是保持线程阻塞所以直至数据变的可以读取之前该线程可以继续做其他的事情。非阻塞写也是如此一个线程请求写入一些数据到某通道但不需要等待它完全写入这个线程同时可以去做别的事情。
通俗理解:NIO是可以做到用一个线程来处理多个操作的。假设有1000个请求过来,根据实际情况可以分配20或者80个线程来处理。不像之前的阻塞IO那样非得分配1000个。49HashSet的底层原理
底层是用hashMap 实现的
HashSet底层使用了哈希表来支持的特点存储快 往HashSet添加元素的时候HashSet会先调用元素的HashCode方法得到元素的哈希值然后通过元素的哈希值经过异或移位等运算就可以算出该元素在哈希表中的存储位置。
多线程并发篇
1.多线程的创建方式
①继承Thread类创建线程类 ②通过Runnable接口创建线程类 ③实现Callable接口通过FutureTask包装器来创建Thread线程 1创建Callable接口的实现类并实现call()方法该call()方法将作为线程执行体并且有返回值。 2创建Callable实现类的实例使用FutureTask类来包装Callable对象该FutureTask对象封装了该Callable对象的call()方法的返 回值。 3使用FutureTask对象作为Thread对象的target创建并启动新线程。 4调用FutureTask对象的get()方法来获得子线程执行结束后的返回值 ④使用ExecutorService、Callable、Future实现有返回结果的多线程也就是使用了ExecutorService来管理前面的三种方式。
2.线程池共同操作同一个对象的如何解决
示例
三个窗口同时出售20张票。
程序分析
1、票数要使用一个静态的值。
2、为保证不会出现卖出同一张票要使用同步锁。
3、设计思路创建一个站台类Station继承THread重写run方法在run方法内部执行售票操作
售票要使用同步锁即有一个站台卖这张票时其他站台要等待这张票卖完才能继续卖票
package com.multi_thread; //站台类
public class Station extends Thread {// 通过构造方法给线程名字赋值public Station(String name) {super(name);// 给线程起名字} // 为了保持票数的一直票数要静态static int tick 20;// 创建一个静态钥匙static Object ob aa;// 值是任意的 Overridepublic void run() {while (tick 0) {// 这个很重要必须使用一个锁进去的人会把钥匙拿在手上出来后把钥匙让出来synchronized (ob) {if (tick 0) {System.out.println(getName() 卖出了第 tick 张票);tick--;} else {System.out.println(票卖完了);}}try {// 休息一秒钟sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}} }
package com.multi_thread;
public class MainClass {// java多线程同步所的使用// 三个售票窗口同时出售10张票public static void main(String[] args) {// 实例化站台对象并为每一个站台取名字Station station1 new Station(窗口1);Station station2 new Station(窗口2);Station station3 new Station(窗口3);// 让每一个站台对象各自开始工作station1.start();station2.start();station3.start();}
}程序运行结果
窗口1卖出了第20张票 窗口3卖出了第19张票 窗口2卖出了第18张票 窗口2卖出了第17张票 窗口3卖出了第16张票 窗口1卖出了第15张票 窗口1卖出了第14张票 窗口3卖出了第13张票 窗口2卖出了第12张票 窗口1卖出了第11张票 窗口3卖出了第10张票 窗口2卖出了第9张票 窗口1卖出了第8张票 窗口3卖出了第7张票 窗口2卖出了第6张票 窗口1卖出了第5张票 窗口3卖出了第4张票 窗口2卖出了第3张票 窗口3卖出了第2张票 窗口1卖出了第1张票
https://www.shuzhiduo.com/A/QW5YQP3e5m/
3.分布式锁有哪几种
①基于数据库实现的乐观锁 version
②基于redis实现的分布式锁
https://blog.csdn.net/weixin_46129192/article/details/126010250
③基于zookeeper实现的分布式锁
https://blog.csdn.net/weixin_52851967/article/details/127575486
4.为什么使用线程池
线程池是一种线程使用模式。线程过多会带来额外的开销其中包括创建销毁线程的开销、调度线程的开销等等同时也降低了计算机的整体性能。线程池维护多个线程等待监督管理者分配可并发执行的任务。这种做法一方面避免了处理任务时创建销毁线程开销的代价另一方面避免了线程数量膨胀导致的过分调度问题保证了对内核的充分利用。 使用线程池有几点好处
降低资源消耗通过池化技术重复利用已创建的线程降低线程创建和销毁造成的损耗。提高响应速度任务到达时无需等待线程创建即可立即执行。提高线程的可管理性线程是稀缺资源如果无限制创建不仅会消耗系统资源还会因为线程的不合理分布导致资源调度失衡降低系统的稳定性。使用线程池可以进行统一的分配、调优和监控。
线程池参数例ThreadPoolTaskExecutor
corePoolSize核心线程数、
maxPoolSize最大线程数、
keepAliveSeconds线程空闲时长
queueCapacity任务队列容量
threadNamePrefix (线程名称前缀)
5.线程的生命周期
线程的生命周期包含5个阶段包括新建、就绪、运行、阻塞、销毁。
新建就是刚使用new方法new出来的线程就绪就是调用的线程的start()方法后这时候线程处于等待CPU分配资源阶段谁先抢的CPU资源谁开始执行;运行当就绪的线程被调度并获得CPU资源时便进入运行状态run方法定义了线程的操作和功能;阻塞在运行状态的时候可能因为某些原因导致运行状态的线程变成了阻塞状态比如sleep()、wait()之后线程就处于了阻塞状态这个时候需要其他机制将处于阻塞状态的线程唤醒比如调用notify或者notifyAll()方法。唤醒的线程不会立刻执行run方法它们要再次等待CPU分配资源进入运行状态;销毁如果线程正常执行完毕后或线程被提前强制性的终止或出现异常导致结束那么线程就要被销毁释放资源;
完整的生命周期图如下
SpringSpringMvc篇
1.对spring的理解
Spring是一个轻量级的IoC/DI和AOP容器的开源框架, 优点 1.Spring 能帮我们低侵入/低耦合地根据配置文件创建及组装对象之间的依赖关系 //解耦 2.Spring 面向切面编程能帮助我们无耦合的实现日志记录性能统计安全控制等 //提高代码重用性 3.Spring 能非常简单的且强大的声明式事务管理 //使用xml或注解的方法,底层用到动态代理 4.Spring 提供了与第三方数据访问框架如JPA无缝集成且自己也提供了一套JDBC模板来方便数据库访问 5.Spring 提供与第三方Web框架无缝集成且自己也提供了一套 SpringMVC 框架来方便 Web 层搭建 ①.1spring底层用到了哪几种设计模式 1.工厂设计模式 : Spring使用工厂模式通过 BeanFactory 、ApplicationContext 创建 bean 对象 2.代理设计模式 : Spring AOP 功能的实现 3.单例设计模式 : Spring 中的 Bean 默认都是单例的 4.模板方法模式 : Spring 中 jdbcTemplate 、hibernateTemplate 等以Template 结尾的对数据库操作类 它们就使用到了模板模式 5.包装器设计模式 : 我们的项目需要连接多个数据库而且不同的客户在每次访问中根据需要会去访问不同的数据库, 这种模式让我们可以根据客户的需求能够动态切换不同的数据源。 6.观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。 7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,spring MVC中也是用到了适配器模式适配 Controller
缺点 使用了大量的反射机制比较占内存而且效率不如直接调用高 Spring包含很多的组件使用的组件越多Spring的启动就会越慢 配置比较复杂不过后来引入了注解配置简化了配置过程 没有做到依赖管理比如控制各依赖之间的版本兼容关系非常麻烦。后续SpringBoot这一点做得很不错。 启动Spring的IOC容器需要依赖第三方的Web服务器自身不能启动 使用Spring做出来的程序逻辑不太清晰代码不直观需要时不时去查看配置才能理解代码 调试阶段不直观不容易定位到Bug的问题所在 原文链接https://blog.csdn.net/qq_17300595/article/details/123678241
2.spring和springboot的区别
· 1、Spring Boot提供极其快速和简化的操作让 Spring 开发者快速上手
2、Spring Boot提供了 Spring 运行的默认配置。
3、Spring Boot为通用 Spring项目提供了很多非功能性特性例如嵌入式 Serve、Security、统计、健康检查、外部配置等等。
3.事务的隔离级别
一、五大事务隔离级别 1、DEAULT默认属性这是一个PlatfromTransactionManager默认的隔离级别使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。 2、READ_UNCOMMITTED 读未提交这是事务最低的隔离级别它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读不可重复读和幻像读是不使用的。 3、READ_COMMITTED 读已提交保证一个事务修改的数据提交后才能被另外一个事务读取另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现但是可能会出现不可重复读和幻像读。默认的事务隔离级别。 4、REPATEBLE_READ可重复读这种事务隔离级别可以防止脏读、不可重复读但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外还保证了不可重复读。 说一下什么是不可重复读。比如一个事务中两次查询一条数据中间有另一个事务修改了数据就出现了不可重复读的情况。 5、 SERIALIZABLE串行化这是花费最高代价但是最可靠的事务隔离级别事务被处理为顺序执行。除了防止脏读、不可重复读外还避免了幻像读。一般不使用效率太低。 说一下什么是幻读。比如比如一个事务中两次查询所有数据中间有另一个事务插入了一条数据这样导致出现了幻读的情况。
4.事务的七大传播机制与五大隔离级别
REQUIRED(0), //使用当前事务如果当前没有事务则自己新建一个事务子方法是必须运行在一个事务中的如果当前存在事务则加入这个事务成为一个整体多用于增删改什么都不写的时候是默认是它 SUPPORTS(1),//如果当前有事务则使用事务如果当前没有事务则不使用事务 mandatory(2)英文发音mændətəri,//该属性强制必须存在一个事务如果当前没有事务就抛出异常 REQUIRES_NEW(3),//如果当前有事务则挂起该事务并且自己创建一个新的事务给自己使用如果没有事务同REQUIRED NOT_SUPPORTED(4),//以非事务方式执行操作如果当前存在事务就把当前事务挂起 never(5),//如果当前存在事务则抛出异常 nested(6)英文发音nestɪd;/如果当前有事务则开启子事务嵌套事务嵌套事务是独立提交或者 回滚如果当前没有事务则同REQUIRED但是如果主事务提交则会携带子事务一 起提交。
如果主事务回滚则子事务一起回滚相反子事务异常则父事务可以混滚或者不回滚。*/
5.springmvc的运行原理
1、 用户发送请求至前端控制器DispatcherServlet。 2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。 3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找)生成处理器对象及处理器拦截 器(如果有则生成)一并返回给DispatcherServlet。 4、 DispatcherServlet调用HandlerAdapter处理器适配器。 5、 HandlerAdapter经过适配调用具体的处理器(Controller也叫后端控制器)。 6、 Controller执行完成返回ModelAndView。 7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。 8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。 9、 ViewReslover解析后返回具体View。 10、DispatcherServlet根据View进行渲染视图即将模型数据填充至视图中。 11、 DispatcherServlet响应用户。
6.SpingIOC/DI的底层实现原理
springIoc:将对象创建和属性赋值的权利交给spring工厂来管理实现解耦合的效果以及集中管理的效果 底层原理是工厂设计模式
SpringAop面向切面编程。在不修改目标代码的情况下为目标类增强额外的功能是功能代码解耦合的效果 应用场景事务控制日志性能监控权限 符合AOP思想的技术SpringAOP, Filter,拦截器 静态代理 1. 优点: 事务功能代码的解耦和. 2. .缺点: 产生大量的代码冗余 底层原理JDK动态代理默认:①基于接口生成的 ②不足如果目标对象没有接口则无法通过JDK动态代理生成代理类 实现目标接口 ②实现目标接口方法 ③开启事务 ④调用目标对象的目标方法 基于继承的动态代理:cglib:实现思路①目标对象 ②增强功能 ③将目标类作为父类 ④组合增强功能和目标对象
7.Springmvc的执行流程
1、用户向服务器发送请求请求被SpringMVC的前端控制器DispatcherServlet分发器截获。 2、DispatcherServlet对请求的URL统一资源定位符进行解析得到URI(请求资源标识符)然后根据该URI调用HandlerMapping获得该Handler配置的所有相关的对象包括Handler处理者对象以及Handler对象对应的拦截器这些对象都会被封装到一个HandlerExecutionChain对象当中返回。 3、DispatcherServlet根据获得的Handler选择一个合适的HandlerAdapter。HandlerAdapter的设计符合面向对象中的单一职责原则代码结构清晰便于维护最为重要的是代码的可复制性高。HandlerAdapter会被用于处理多种Handler调用Handler实际处理请求的方法。 4、提取请求中的模型数据开始执行Handler(Controller)。 //在填充Handler的入参过程中根据配置spring将帮助做一些额外的工作 消息转换将请求的消息如json、xml等数据转换成一个对象将对象转换为指定的响应信息。 数据转换对请求消息进行数据转换如String转换成Integer、Double等。 数据格式化对请求的消息进行数据格式化如将字符串转换为格式化数字或格式化日期等。 数据验证验证数据的有效性如长度、格式等验证结果存储到BindingResult或Error中。 5、Handler执行完成后向DispatcherServlet返回一个ModelAndView对象ModelAndView对象中应该包含视图名或视图模型。 6、根据返回的ModelAndView对象选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet。 7、ViewResolver结合Model和View来渲染视图。 8、将视图渲染结果返回给客户端。 以上8个步骤DispatcherServlet、HandlerMapping、HandlerAdapter和ViewResolver等对象协同工作完成SpringMVC请求—响应的整个工作流程这些对象完成的工作对于开发者来说都是不可见的开发者并不需要关心这些对象是如何工作的开发者只需要在Handler(Controller)当中完成对请求的业务处理。
8.工厂模式、简单工厂模式、抽象工厂模式三者的区别
1、创建对象不同。创建对象时“工厂模式”使用Factory模式替代使用new创建对象“简单工厂模式”使用fw模式建立对象“抽象工厂模式”则使用迭代模式创建对象。 2、定义变量不同。“工厂模式”不用事先定义变量使用时随时引用便可。“简单工厂模式”使用参数或者配置文件等事先定义好的变量然后利用分支判断初始化具体产品类并返回。“抽象工厂模式则”不符合“开发-封闭”原则每次增加产品都需要修改类方法。 3、接口数量不同。“工厂模式”有两至三个接口。“简单工厂模式”只有一个接口。抽象工厂模式理论上具有无限个接口。
9.Spring循环依赖如何解决
spring是通过缓存来解决循环依赖的问题的
1.一级缓存用于存放完全初始化好的bean
2.二级缓存存放原始的bean对象(尚未填充属性)用于解决循环依赖
3.三级缓存存放bean工厂对象用于解决循环依赖
Mybatis篇
1.mybatis的注解有哪些 Mapper Param Repository2.mybatis的缓存
https://blog.csdn.net/Progran_ape/article/details/104181926
Mybatis的一级缓存是基于sqlSession实现的是系统默认的
1、不需要配置默认开启。
2、无法管理一级缓存
3、不得不用无法剔除
Mybatis的二级缓存机制是基于key,value形式存储的key就是namespace,value中有个map,map中以namespace作为key,查询到的结果作为结果
1、查出的数据首先放在一级缓存中只有一级缓存被关闭或者提交以后一级缓存数据才会转移到二级缓存
2、可以关闭
3、基本上都是关闭的被redis等其他缓存所替代
二级缓存实现https://blog.csdn.net/qq_59025975/article/details/121929522
3.#{} 和 ${} 的区别是什么
两者在 MyBatis 中都可以作为 SQL 的参数占位符在处理方式上不同 #{}在解析 SQL 的时候会将其替换成 ? 占位符然后通过 JDBC 的 PreparedStatement 对象添加参数值这里会进行预编译处理可以有效地防止 SQL 注入提高系统的安全性 ${}在 MyBatis 中带有该占位符的 SQL 片段会被解析成动态 SQL 语句根据入参直接替换掉这个值然后执行数据库相关操作存在 SQL注入 的安全性问题
SpringBoot篇
1.springboot的优点
优点一、独立运行 Spring Boot而且内嵌了各种servlet容器Tomcat、Jetty等现在不再需要打成war包部署到容器中 Spring Boot只要打成一个可执行的jar包就能独立运行所有的依赖包都在一个jar包内。 二、简化配置 spring-boot-starter-web启动器自动依赖其他组件简少了maven的配置。 三、自动配置 Spring Boot能根据当前类路径下的类、jar包来自动配置bean如添加一个spring-boot-starter-web启 动器就能拥有web的功能无需其他配置。 四、无代码生成和XML配置 Spring Boot配置过程中无代码生成也无需XML配置文件就能完成所有配置工作这一切都是借助于 条件注解完成的这也是Spring4.x的核心功能之一。 五、应用监控 Spring Boot提供一系列端点可以监控服务及应用做健康检测。
2、运行Spring Boot有哪几种方式
1.打包用命令或者放到容器中运行 2.用 Maven/Gradle 插件运行 3.直接执行 main 方法运行 三、Spring Boot 的核心注解是哪个它主要由哪几个注解组成的 启动类上面的注解是SpringBootApplication它也是 Spring Boot 的核心注解主要组合包含了以下 3 个注解 SpringBootConfiguration组合了 Configuration 注解实现配置文件的功能。 EnableAutoConfiguration打开自动配置的功能也可以关闭某个自动配置的选项如关闭数据源 自动配置功能 SpringBootApplication(exclude { DataSourceAutoConfiguration.class })。
分布式篇springcloud和dubbo以及ZooKeeper
1.yml的优先级
当properties、yaml和yml三种文件路径相同时三个文件中的配置信息都会生效但是当三个文件中有配置信息冲突时加载顺序是:
yml yaml propertiesbootstrap.yml跟application.yml加载顺序
bootstrap.ymlbootstrap.properties用来在程序引导时执行应用于更加早期配置信息读取如可以使用来配置application.yml中使用到参数等application.ymlapplication.properties) 应用程序特有配置信息可以用来配置后续各个模块中需使用的公共参数等。
bootstrap.yml 先于 application.yml 加载
2.SpringCloud微服务的拆分粒度
原则1划分为10个微服务模块 一个传统的单体应用在进行划分的时候最好不要超过10个微服务模块。注意这里指的业务功能模块不包括底层的系统管理流程引擎等技术模块。业务功能流程之间基本没有任何耦合性的多拆分也不影响 原则2强数据关联模块不要拆分 简单来说就是有些系统基本就是围绕一个核心数据或业务对象展开的管理系统比如我们说的资源管理系统资产管理系统等。 原则3以数据聚合驱动业务功能聚合 这个理解起来困难简单来说就是微服务划分不仅仅是上层业务功能模块划分而且包括了数据库的拆分因此在划分微服务的时候首先要考虑数据域的拆分基于数据和功能的CRUD分析来考虑数据的聚合关联要求。先拆分好数据域再来考虑数据域里面有哪些业务功能。 原则4从纵向功能划分思路到横向分层思路转变 在微服务划分里面同样需要结合SOA的横向分层思想即 传统的单体应用你会发现在进行微服务划分的时候本身微服务也体现出分层属性即有些属于底层的业务对象实体数据提供类微服务有些数据业务功能和规则类微服务而还有些属于上层的流程和服务功能组合类微服务。 因此在进行微服务划分的时候应该从数据-》功能规则-》流程的分层模型维度综合考虑。 原则5高内聚松耦合的基础原则 在进行微服务拆分的时候高内聚松耦合的原则不变。而如何确保拆分的数据库拆分的业务功能模块满足高内聚松耦合的原则。
3.Eureka集群的孤岛效应
4.springcloud负责均衡的策略
负载均衡分为服务端负载均衡和客户端负债均衡 服务端负载均衡器的问题是它提供了更强的流量控制权但无法满足不同的消费者希望使用不同负载均衡策略的需求而使用不同负载均衡策略的场景确实是存在的 所以客户端负载均衡就提供了这种灵活性 客户端负载均衡Ribbon睿笨为springclond 1.轮询策略 第一次调用服务 1第二次调用服务 2第三次调用服务3 2.权重策略 响应时间越长权重越低选中概率就越低 3.随机策略 随机分配 4.最小连接数策略 取连接数最小的一个服务实例。如果有相同的最小连接数那么会调用轮询策略进行选取 5.重试策略 按照轮询策略来获取服务如果获取的服务实例为 null 或已经失效则在指定的时间之内不断地进行重试来获取服务如果超过指定时间依然没获取到服务实例则返回 null 6.可用性敏感策略 过滤掉非健康的服务实例然后再选择连接数较小的服务实例 7.区域敏感策略 根据服务所在区域zone的性能和服务的可用性来选择服务实例在没有区域的环境下该策略和轮询策略类似
5.springcloud的核心组件
https://blog.csdn.net/web18334137065/article/details/125244487 springcloud的五大组件包括Netflix EurekNetflix RibbonNetflix HystrixNetflix Zuul和Spring Cloud Config。 五个组件分别对应1服务发现2客服端负载均衡3断路器4服务网关5分布式配置。各组件分工有别协调统一。
6…dubbo: 其核心部分包含:
服务提供者Provider暴露服务的服务提供方服务提供者在启动时向注册中心注册自己提供的服务。 服务消费者Consumer: 调用远程服务的服务消费方服务消费者在启动时向注册中心订阅自己所需的服务服务消费者从提供者地址列表中基于软负载均衡算法选一台提供者进行调用如果调用失败再选另一台调用。 注册中心Registry注册中心返回服务提供者地址列表给消费者如果有变更注册中心将基于长连接推送变更数据给消费者 监控中心Monitor服务消费者和提供者在内存中累计调用次数和调用时间定时每分钟发送一次统计数据到监控中心 Container服务运行容器
7.Dubbo 和 Spring Cloud 有什么区别
(1).Dubbo 使用的是 RPC 通信而 Spring Cloud 使用的是 HTTP RESTFul 方式。 (2):dubbo的服务注册中心使用的是Zookeeperspringclond使用的是Eureka (3):dubbo分布式配置和分布式网关相比于springclond都没有 (4):dubbo的短路器不完善springcloud的比较完善
8.Dubbo默认使用的是什么通信框架还有别的选择吗
Dubbo 默认使用 Netty 框架也是推荐的选择另外内容还集成有Mina、Grizzly。dubbo不支持分布式事务
Mysql篇
1.事务的特性
MySQL 事务具有四个特性原子性、一致性、隔离性、持久性这四个特性简称 ACID 特性 (1)、原子性Atomicity 一个事务是一个不可再分割的整体要么全部成功要么全部失败 (2)、一致性Consistency 事务执行前后属于一致性状态 (3)、隔离性Isolution 一个事务不受其他事务的影响并且多个事务彼此隔离 (4)、持久性Durability 一个事务一旦被提交在数据库中的改变就是永久的提交后就不能再回滚
2.数据库的隔离级别
分别是读未提交(read uncommitted )、读已提交(read committed)、可重复读(repeatable read)、序列化\串行化(serializable)。 (1) 读 未提交(read uncommitted)脏读 假如A事务和B事务对同一张表进行操作B事务进行了DML语句但没有提交(commit)或者回滚(rollback)此时A事务便可以查看到B事务还没有提交的数据就是保存在事务性活动的日志文件中的数据。这样可能会造成脏读。何为脏读脏读就是B事务还没有提交的数据A事务便可以查看到在用户的眼里A用户就会以为这条数据已经存在了其实还没有提交如果提交失败便会回滚这条数据并没有添加成功而A用户却以为成功了 (2读 已提交(read committed)不可重复读 假如A事务和B事务对同一张表进行操作B事务进行了DML(数据操作)语句但没有进行提交那么A事务是读取不到的它解决了脏读但是出现了不可重复读。 (3) 可重复读(repeatable read) 幻读 A事务读取不到B事务还没有提交的数据解决了不可重复读但会造成幻影读幻读数据不够真实。mysql中默认的事务隔离级别就是这个。 (4)序列化\串行化(serializable) 这个隔离级别是最高级别效率最低但是非常安全不能并发俩个事务不能对同一张表进行操作需要等待A事务操作完之后B事务才能进行操作。每次读取的数据都是最真实的。
3.索引的分类以及索引的底层原理
索引的分类 (1) 普通索引最基本的索引它没有任何限制。 (2) 唯一索引与普通索引类似不同的就是索引列的值必须唯一但允许有空值。如果是组合索引则列值的组合必须唯一。 (3) 主键索引它是一种特殊的唯一索引用于唯一标识数据表中的某一条记录不允许有空值一般用 primary key 来约束。 (4) 联合索引(又叫复合索引)多个字段上建立的索引能够加速复合查询条件的检索。 (5) 全文索引老版本 MySQL 自带的全文索引只能用于数据库引擎为 MyISAM 的数据表新版本 MySQL 5.6 的 InnoDB 支持全文索引。默认 MySQL 不支持中文全文检索可以通过扩展 MySQL添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文。 索引的底层 B (1):二叉树Binary Search Trees 二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”left subtree和“右子树”right subtree。二叉树常被用于实现二叉查找树和二叉堆。二叉树有如下特性 1、每个结点都包含一个元素以及n个子树这里0≤n≤2。 2、左子树和右子树是有顺序的次序不能任意颠倒。左子树的值要小于父结点右子树的值要大于父结点。
4.Mysql优化
https://blog.csdn.net/iiiiiiiiiooooo/article/details/123583743 在设计上字段类型存储引擎范式 在功能上索引缓存分库分表 在架构上集群主从复制负载均衡读写分离 2.
1.在读表的时候尽可能的避免全表扫描合理的根据业务需求在where及order by涉及的列上建立索引。
2.应尽量避免在where字句中使用! 或 操作符否则将引擎会放弃索引而走全表扫描。
3.尽量避免where字句中对字段进行null值判断否则也会导致引擎放弃索引而走全表扫描。可以用0代替判断前提是保证字段不能为null。
4.尽量避免在where字句中用or拼接否则也会走全表扫描。可以通过union all 拼接代替。
5.尽量不适用Like做搜索查询诺要提高效率可以采用全文检索。
6.尽量不适用In 或 Not in查询否则会导致全表扫描。对于连续的数字可以用between 代替 in。比如select id from t where num between 1 and 3
5.mysql的模糊查询mysql自带的函数mysql的去重查重
6.Sql注入 是怎么实现的
攻击者通过web 应用程序利用SQL语句或字符串将非法的数据插入到服务端数据库中获取数据库的用户管理权限然后将数据库管理用户权限提升至操作系统管理用户权限控制服务器操作系统获取重要的信息和机密文件
7.MySQL存储引擎InnoDB和MyISAM的区别
InnoDB是事务型数据库的首选引擎是目前MYSQL的默认事务型引擎是目前最重要、使用最广泛的存储引擎。支持事务安全表ACID支持行锁定和外键。 MyISAM是MySQL 的引擎之一不支持数据库事务也不支持行级锁和外键。 如何选择InnoDB和MyISAM 1.InnoDB如果需要对事务的完整性要求比较高比如银行要求实现并发控制比如售票那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库也可以选择InnoDB因为支持事务的提交和回滚。 2.MyISAM读取数据快空间和内存使用比较低。如果表主要是用于读取记录那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低也可以使用。
8.InnoDB和MyISAM的区别
1.InnoDB是MySQL默认的存储引擎。 2.只有 InnoDB 支持事务MyISAM不支持事务。 3.MyISAM不支持行级锁和外键 InnoDB支持。 4.InnoDB表的大小更加的大用MyISAM可省很多的硬盘空间。 5.InnoDB 引擎的索引和文件是存放在一起的,找到索引就可以找到数据,是聚簇式设计。 6.MyISAM 引擎采用的是非聚簇式(即使是主键)设计,索引文件和数据文件不在同一个文件中。
9.行锁
比如事务 A 更新了一行而这时候事务 B 也要更新同一行则必须等事务 A 的操作完成后才能进行更新
10.聚集索引和非聚集索引的区别
区别 1.聚集索引一个表只能有一个而非聚集索引一个表可以存在多个 2.聚集索引存储记录是物理上连续存在而非聚集索引是逻辑上的连续物理存储并不连续 3.聚集索引:物理存储按照索引排序聚集索引是一种索引组织形式索引的键值逻辑顺序决定了表数据行的物理存储顺序。 4.非聚集索引:物理存储不按照索引排序非聚集索引则就是普通索引了仅仅只是对数据列创建相应的索引不影响整个表的物理存储 顺序。 5.索引是通过二叉树的数据结构来描述的我们可以这么理解聚簇索引索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索 引节点只不过有一个指针指向对应的数据块。
优势与缺点 聚集索引插入数据时速度要慢时间花费在“物理存储的排序”上也就是首先要找到位置然后插入查询数据比非聚集数据的速度快
11.mysql索引有几种类型
1.唯一索引索引列的值必须唯一可以允许空值
2.主键索引主键索引是特殊的唯一索引不允许有空值
3.普通索引没有限制值可以为Null,加快查询条件
4.联合索引
12.mysql查询重复数据
select 字段名,count(*) from employee group by employee_name having count(employee_name)1;
13.EXPLAIN关键字的解释
reids篇
1.redis介绍
基于内存读写操作的数据库. 简介: Redis是使用C语言编写的数据库, NoSQL数据库, Redis采用了非阻塞式IO,使用key-value的形式保存数据 not only sql: (非关系型数据,二维表,) 存: key— value 取: key— 特点:
1.基于内存操作,速度最快.
2.非关系型数据库, 没有table column,row数据概念, key-value保存数据
3.独立服务器的内存 空间. (不会竞争tomcat内部的jvm空间)
4.内部的命令执行: 单线程.(线程安全)
2.单线程为什么快
1.就是它本身是单线程的单线程避免了操作共享变量上下文切换的开销而且本身基于内存操作速度很快
2.就是它利用I/O多路复用机制拥有高效的线程模型可以让主线程在执行过程中不会有网络I/O的阻塞
https://www.jianshu.com/p/05d348eda81f
2.数据结构
redis是一个基于key-value的存储key是string类型value可以是string(字符串)、哈希表hash,列表list、集合set、有序集合sorted set等
3.持久化方式
一种是快照(RDB)一种是日志增量备份(AOF)快照是某一时间的瞬时记录我可以在5秒钟进行一次存储也可以10秒进行一次存储优点是效率高缺点是如果还没有到时间数据就遗失了会造成数据丢失 日志增量备份(AOF)就是你写一条我保存一条好处是数据不容易遗失坏处是效率低
4.淘汰策略与过期策略
过期策略 定时删除惰性删除 定时删除:可以通过redis的配置文件hz配置1s执行几次定期删除 惰性删除惰性删除不是去主动删除而是在你要获取某个key 的时候redis会先去检测一下这个key是否已经过期如果没有过期则返回给你如果已经过期了那么redis会删除这个key不会返回给你 内存淘汰策略 1.noeviction 不进行数据淘汰也是Redis的默认配置。这时当缓存被写满时再有写请求进来Redis不再提供服务直接返回错误。 2.volatile-random 缓存满了之后在设置了过期时间的键值对中进行随机删除。 3.volatile-ttl 缓存满了之后会针对设置了过期时间的键值对中根据过期时间的先后顺序进行删除,越早过期的越先被删除。 4.volatile-lru 缓存满了之后针对设置了过期时间的键值对采用LRU算法进行淘汰。 5.volatile-lfu 缓存满了之后针对设置了过期时间的键值对采用LFU的算法进行淘汰。 6.allkeys-random 缓存满了之后从所有键值对中随机选择并删除数据。 7.allkeys-lru 缓存满之后使用LRU算法在所有的数据中进行筛选删除。 8.allkeys-lfu 缓存满了之后使用LFU算法在所有的数据中进行筛选删除。
4.应用场景
如计数器点赞或者阅读量缓存或者是分布式锁
5.redis实现缓存的时候怎么保证mysql和redis数据一致
1.增删改的时候查一下redis是否缓存上然后删除redis,再插入数据库再更新redis
6.为什么要用redis:
第一、redis是基于内存存储计算性能速读远超mysql等数据库计算速度很快所以在使用的时候数据响应很快 第二、redis支持多种多样的数据结构如字符串、tree、ztree、map、等这些丰富的数据结构可以满足我们在开发工作大部分常见数据结构进行存储。 第三、redis丰富的api支持让我们在使用的时候常见的查询存储都能够很方便的使用支持自定的查询的api等等 第四、redis的生态比较成熟很多家大型公司都在使用很多相关的知识扩展以及分析 第五、redis分布式集群化扩展性极高而且稳定能够支撑大量的数据吞吐只要硬件支持。
7.哨兵和集群
https://blog.csdn.net/qq_39230153/article/details/121524461
哨兵的由来redis主从切换技术当主机宕机后需要手动把一台从slave服务器切换为主服务器这就需要人工干预费时费力还回造成一段时间内服务不可用所以推荐哨兵架构Sentinel来解决这个问题.
哨兵模式是一种特殊的模式首先Redis提供了哨兵的命令哨兵是一个独立的进程作为进程它独立运行。其原理是哨兵通过发送命令等待Redis服务器响应从而监控运行的多个Redis实例。
简而言之redis主从复制的主机宕机时哨兵会自动的会把从机换成主机一个哨兵可能会有问题可以多哨兵进行监控这就是多哨兵模式哨兵1认为主机不可用时主观下线当后面的哨兵也认为不可用时数量达到一定时会进行投票进行failover故障转移操作转移成功后就会发布订阅模式让各个哨兵把自己监控的从服务器实现切换主机这一过程称为 客观下线
8.redis的缓存机制
9.Redis的击穿、雪崩和穿透
雪崩击穿穿透
https://zhuanlan.zhihu.com/p/469677754 1缓存雪崩 是指在短时间内有大量缓存同时过期导致大量的请求直接查询数据库从而对数据库造成了巨大的压力严重情况下可能会导致数据库宕机的情况叫做缓存雪崩 解决方法加锁排队相当于单例模式的双重加锁机制如果是分布式情况下需要用到分布式锁 2缓存穿透 说白了就是查询一个一定不存在的数据由于缓存是未命中从数据库去查询查不到数据则不写入缓存这将导致这个不存在的数据每次请求都要到数据库去查询造成缓存穿透 解决方法1.布隆过滤器我们可以使用布隆过滤器来解决,可以将布隆过滤器想象成一个map,请求一个不存在的数据,我们就把它放到这个map中每次请求前先通过map过滤一遍如果map中存在这个值就直接将请求拦截掉。 2.缓存空结果我们可以把每次从数据库查询的数据都保存到缓存中我们可以将空结果的缓存时间设置得短一些例如 1-3 分钟。 3缓存击穿指的是某个热点缓存在某一时刻恰好失效了然后客户端访问数据的时候redis中没有数据mysql中有数据相当于直接跳过了redis。 解决方法 1.加锁排队 在查数据库时进行加锁缓冲大量请求, 以减少数据库压力
2.设置永不过期 对于某些热点缓存我们可以设置永不过期这样就能保证缓存的稳定性但需要注意在数据更改之后要及时更新此热点缓存不然就会造成查询结果的误差。 (4):缓存预热 缓存预热并不是一个问题而是使用缓存时的一个优化方案它可以提高前台用户的使用体验。 缓存预热指的是在系统启动的时候先把查询结果预存到缓存中以便用户后面查询时可以直接从缓存中读取以节约用户的等待时间。
10.redis读写分离主从复制
11.什么时候用memcached跟redis比有啥好处
(1) memcached所有的值均是简单的字符串redis作为其替代者支持更为丰富的数据类型 (2) redis的速度比memcached快很多 (3) redis可以持久化其数据 Memcached支持的数据结构很单一仅支持string类型的操作。并且对于value的大小限制必须在1MB以下过期时间不能超过30天 由于 Redis 只使用单核而 Memcached 可以使用多核所以平均每一个核上 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中Memcached 性能要高于 Redis。虽然 Redis 最近也在存储大数据的性能上进行优化但是比起 Memcached还是稍有逊色。
12.什么是哨兵
Sentinel(哨兵)是用于监控Redis集群中Master状态的工具是Redis高可用解决方案哨兵可以监视一个或者多个redis master服务以及这些master服务的所有从服务。 某个master服务宕机后会把这个master下的某个从服务升级为master来替代已宕机的master继续工作。 顺带提一句即使后来之前的master重启服务也不会变回master了而是作为slave从服务
13.redis分布式锁应用在哪些方面
基于数据库的分布式锁 悲观锁乐观锁【version】。 基于缓存实现分布式锁 用redissetnx, redlock… 基于zookeeper实现的分布式锁 之前的理解zookeeper是用来为管理集群的比如做load balancing之类的。用于管理协调大量服务器集群。但是实际 zookeeper是一个为分布式应用提供一致性服务的开源组件。它内部是一个分层的文件系统目录树结构规定同一个目录下只能有一个唯一文件名。它也可以实现分布式锁
mq 解耦、异步、削峰。
rabbitmq
如何保证消息队列的高可用 RabbitMQ 有三种模式单机模式、普通集群模式、镜像集群模式。
2.如何保证消息不被重复消费或者说如何保证消息消费的幂等性
加全局唯一的 id看是否被消费过
3.如何保证消息的可靠性传输或者说如何处理消息丢失的问题
确保说写 RabbitMQ 的消息别丢可以开启 confirm 模式在生产者那里设置开启 confirm 模式之后你每次写的消息都会分配一个唯一的 id 然后如果写入了 RabbitMQ 中RabbitMQ 会给你回传一个 ack 消息告诉你说这个消息 ok 了。如果 RabbitMQ 没能处理这个消息会回调你的一个 nack 接口 告诉你这个消息接收失败你可以重试。而且你可以结合这个机制自己在内存里维护每个消息 id 的状态如果超过一定时间还没接收到这个消息的回调那么你可以重发 开启 RabbitMQ 的持久化
Linux篇
1.linux的最小执行单元是进程
2.nginx
简介Nginx是一个 轻量级/高性能的反向代理Web服务器用于 HTTP、HTTPS、SMTP、POP3 和 IMAP 协议。他实现非常高效的反向代理、负载平衡他可以处理2-3万并发连接数官方监测能支持5万并发现在中国使用nginx网站用户有很多例如新浪、网易、 腾讯等 Nginx 有哪些优点 跨平台、配置简单。 非阻塞、高并发连接处理 2-3 万并发连接数官方监测能支持 5 万并发。 内存消耗小开启 10 个 Nginx 才占 150M 内存。 成本低廉且开源。 稳定性高宕机的概率非常小。 内置的健康检查功能如果有一个服务器宕机会做一个健康检查再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上 Nginx 负载均衡的算法怎么实现的?策略有哪些? 1.1 .轮询(默认) 2.权重 weight 3.ip_hash( IP绑定)
3.shell是如何传递参数的
ehco
ELK篇(Elasticsearch , Logstash, Kibana)
ELK(Elasticsearch , Logstash, Kibana) 1.1、Elasticsearch是个开源分布式搜索引擎提供搜集、分析、存储数据三大功能。它的特点有分布式零配置自动发现索引自动分片索引副本机制restful风格接口多数据源自动搜索负载等。 1.2、Logstash 主要是用来日志的搜集、分析、过滤日志的工具支持大量的数据获取方式。一般工作方式为c/s架构client端安装在需要收集日志的主机上server端负责将收到的各节点日志进行过滤、修改等操作在一并发往elasticsearch上去。 1.3、Kibana 也是一个开源和免费的工具Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面可以帮助汇总、分析和搜索重要数据日志。 es使用了倒排索引而倒排索引是通过分词策略形成了词和文章的映射关系表这种词典映射表即为倒排索引。有了 倒排索引就能实现 o1时间复杂度的效率检索文章了极大的提高了检索效率 1.es是什么 elasticsearch简写eses是一个高扩展、开源的全文检索和分析引擎它可以准实时地快速存储、搜索、分析海量的数据
JVM篇
1.jvm数据结构和内存调优 jvm的回收机制
①堆、栈、程序计数器、方法区、本地方法栈
1堆内存是JVM中最大的一块由年轻代和老年代组成而年轻代内存又被分成三部分Eden空间、From Survivor空间、To Survivor空间,默认情况下年轻代按照8:1:1的比例来分配 2方法区存储类信息、常量、静态变量等数据是线程共享的区域 3 栈又分为java虚拟机栈和本地方法栈主要用于方法的执行。 控制参数 -Xms设置堆的最小空间大小。 -Xmx设置堆的最大空间大小。 -XX:NewSize设置新生代最小空间大小。 -XX:MaxNewSize设置新生代最大空间大小。 -XX:PermSize设置永久代最小空间大小。 -XX:MaxPermSize设置永久代最大空间大小。 -Xss设置每个线程的堆栈大小。 1.1Java堆是垃圾收集器管理的主要区域因此很多时候也被称做“GC堆”。如果从内存回收的角度看由于现在收集器基本都是采用的分代收集算法所以Java堆中还可以细分为新生代和老年代再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。 2.1方法区Method Area与Java堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分但是它却有一个别名叫做Non-Heap非堆目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说很多人愿意把方法区称为“永久代”Permanent Generation本质上两者并不等价仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区或者说使用永久代来实现方法区而已。 ②内存调优 1.参数调优 2.调优工具之jps(Java Virtual Machine Process Status Tool) ③标记清除算法 2.标记复制算法
2.类加载机制
双亲委派模式,即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器.父类 加载器能够完成加载则成功返回,不能则子类加载器才自己尝试加载.
https://blog.csdn.net/weixin_59262008/article/details/125676787
3.Java的垃圾回收机制
https://blog.csdn.net/weixin_53975556/article/details/125916780
https://blog.csdn.net/qq_35246620/article/details/80522720?ops_request_misc%257B%2522request%255Fid%2522%253A%2522166256320316782417032003%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257Drequest_id166256320316782417032003biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~hot_rank-1-80522720-null-null.142v47body_digest,201v3control_2utm_termJava%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%9C%BA%E5%88%B6spm1018.2226.3001.4449
垃圾回收机制分为两种自动回收垃圾机制
自动垃圾回收机制
在 Java 世界中几乎所有的对象实例都在堆中存放所以垃圾回收也主要是针对堆来进行的。通过垃圾判断算法引用计数法、可达性分析法判断堆内存中是否存在垃圾如果存在则使用垃圾回收算法标记-清除算法、标记-整理算法、复制算法、分代收集算法来进行垃圾回收
23种设计模式https://zhuanlan.zhihu.com/p/575645658
创建型模式共五种工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式共七种适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式共十一种策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式的六大原则
1开闭原则 开闭原则指的是对扩展开放对修改关闭。在对程序进行拓展时不能去修改原有的代码使用抽象类或接口。
2依赖倒转原则依赖倒转原则是开闭原则的基础系统面向接口编程依赖于抽象而不依赖于具体。
3里氏替换原则里氏替换原则指的是任何基类出现的地方子类一定可以出现。里氏替换原则是对开闭原则的补充实现开闭原则的关键是抽象化而基类与子类的继承关系就是抽象化的具体实现所以里氏替换原则是对实现抽象化的具体步骤的规范。
4接口隔离原则使用多个隔离的接口比使用单个接口好降低接口之间的耦合度和依赖。
5迪米特原则最少知道原则。一个类应当尽量减少与其他实体类相互作用使得系统功能模块相对独立降低耦合度。
6合成复用原则尽量使用组合/聚合的方式而不是继承。
MQTT与EMQX
MQTT属于是物联网的通信协议在MQTT协议中有两大角色客户端发布者/订阅者服务端Mqtt broker针对客户端和服务端需要有遵循该协议的的具体实现EMQ/EMQ X就是MQTT Broker的一种实现。
EMQ X 是开源百万级分布式 MQTT 消息服务器MQTT Messaging Broker用于支持各种接入标准 MQTT协议的设备实现从设备端到服务器端的消息传递以及从服务器端到设备端的设备控制消息转发。从而实现物联网设备的数据采集和对设备的操作和控制
https://www.emqx.io/docs/zh/v4.3/backend/backend.html
https://cloud.tencent.com/developer/article/1860436