框架Spring框架中的单例bean不是线程安全的
1、当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对该单列状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。
2、Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程安全和并发问题需要开发者自行去搞定。
比如:我们通常在项目中使用的Spring bean都是不可变的状态(比如Service类和DAO类),所以在某种程度上说Spring的单例bean是线程安全的。
3、如果你的bean有多种状态的话(比如 View Model对象),就需要自行保证线程安全。最浅显的解决办法就是将多态bean的作用由“singleton”变更为“prototype”。
AOP面向切面编程 aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般比如可以做为公共日志保存,事务处理等
举例操作日志:
主要思路是这样的,使用a ...
MySQL索引帮助MySQL高效获取数据的数据结构,主要是用来提高数据检索的效率,降低数据库的IO成本,同时通过索引列对数据进行排序,降低数据排序的成本,也能降低了CPU的消耗
索引的底层数据结构MySQL的默认的存储引擎InnoDB采用的B+树的数据结构来存储索引,选择B+树的主要的原因是:
第一、阶数更多,路径更短
第二、磁盘读写代价B+树更低,非叶子节点只存储指针,叶子节点存储数据
第三、B+树便于扫库和区间查询,叶子节点是一个双向链表
B树和B+树的区别第一:在B树中,非叶子节点和叶子节点都会存放数据,而B+树的所有的数据都会出现在叶子节点,在查询的时候,B+树查找效率更加稳定
第二:在进行范围查询的时候,B+树效率更高,因为B+树都在叶子节点存储,并且叶子节点是一个双向链表
聚簇索引与非聚簇索引聚簇索引主要是指数据与索引放到一块,B+树的叶子节点保存了整行数据,有且只有一个,一般情况下主键在作为聚簇索引的。
非聚簇索引值的是数据与索引分开存储,B+树的叶子节点保存对应的主键,可以有多个,一般我们自己定义的索引都是非聚簇索引
回表查询回表的意思就是通过二级索引找到对应的主键值, ...
JVMJVM组成JVM的组成与运行流程JVM中共有四大部分,分别是ClassLoader(类加载器)、Runtime Data Area(运行时数据区,内存分区)、Execution Engine(执行引擎)、Native Method Library(本地库接口)
它们的运行流程是:
第一,类加载器(ClassLoader)把Java代码转换为字节码
第二,运行时数据区(Runtime Data Area)把字节码加载到内存中,而字节码文件只是JVM的一套指令集规范,并不能直接交给底层系统去执行,而是有执行引擎运行
第三,执行引擎(Execution Engine)将字节码翻译为底层系统指令,再交由CPU执行去执行,此时需要调用其他语言的本地库接口(Native Method Library)来实现整个程序的功能。
类加载器JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。
类加载器类别常见的类加载器有4个
第一个是启动类加载器(BootStrap ClassLoader):其是由C++编写实现。用 ...
Java集合1、常见的集合类 java中提供了大量的集合类,主要分为两类:
1、Collection 属于单列集合 有两个接口List 和 Set
List常见的:ArrayList 和 LinkedList
Set常见的:HashSet(无序) 和 TreeSet(需要排序)
2、Map 属于双列集合
常见的有HashMap 、 TreeMap
线程安全的有:ConcurrentHashMap
2、ArrayList
底层数据结构
ArrayList底层是用动态的数组实现的
初始容量
ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10
扩容逻辑
ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组
添加逻辑
确保数组已使用长度(size)加1之后足够存下下一个数据
计算数组的容量,如果当前数组已使用长度+1后的大于当前的数组长度,则调用grow方法扩容(原来的1.5倍)
确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
返回添加成功布尔值 ...
Java多线程1、线程的基本知识并行与并发的区别并行是同一时间能做多件事的能力,比如A核CPU同时执行4个线程
并发是同一时间应对多件事情的能力,多个线程轮流使用一个或多个CPU
并发的理解:宏观并行,微观串行
线程与进程的区别
进程是正在运行程序的示例,进程中包含了线程,每个线程执行不同的任务
不同的线程使用不同的内存空间,在当前进程下的所有线程可以共享内存空间
线程更轻量,线程的上下文切换成本一般上要比进程低
java中创建线程的方式4种常见的创建方式
1、继承Thread类
2、实现runnable接口
3、实现Callable接口
4、线程池创建线程
通常情况下项目中都会选择线程池的方式创建线程
runnable 和 callable 两个接口创建线程有什么不同呢?1、最主要的区别是有无返回值
Runnable接口run方法无返回值
Callable接口call方法有返回值,是个泛型,和Future、FutureTask配合可以用来获取异步执行的结果
2、异常处理不同
Runnable接口run方法只能抛出运行时异常,也无法捕获处理
Callable接口cal ...
SQL优化1、SQL语句方面1、避免使用select *select 不走覆盖索引,会有大量的回表操作,从而导致查询SQL的性能很低。应该使用具体的字段代替,只返回使用到的字段。
多查出来的数据,通过网络IO传输的过程中,也会增加数据传输的时间。
2、用union all代替union使用union关键字后,可以获取排重后的数据。而如果使用union all关键字,可以获取所有数据,包含重复的数据。排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源。
3、小表驱动大表in关键字,他会优先执行in里面的子查询语句,然后在执行in外面的语句,in里面的数据量很少,作为条件查询速度更快。
exists关键字,他会优先执行exists左边的语句(即主查询语句),然后把它作为条件,去跟右边的语句匹配,如果匹配上,则可以查出数据,如果匹配不上,数据就被过滤掉了。
in 适用于左边大表,右边小表。
exists 适用于左边小表,右边大表。
4、多用limit尽量避免取出自己不需要的数据,同时还能让误操作的影响降低
5、in中值太多查询语句一次性可能会查询出非常多的数据,很容易导致接口超时。如 ...
Java设计模式背景
在面向对象编程中,创建对象实例最常用的方式就是通过 new 操作符构造一个对象实例,但在某些情况下,new 操作符直接生成对象会存在一些问题。
举例来说,对象的创建需要一系列的步骤:可能需要计算或取得对象的初始位置、选择生成哪个子对象实例、或在生成之前必须先生成一些辅助对象。
在这些情况,新对象的建立就是一个 “过程”,而不仅仅是一个操作,就像一部大机器中的一个齿轮传动。
类型
简单工厂模式(Simple Factory)
后来出现了工厂,用户不再需要去创建宝马车,由工厂进行创建,想要什么车,直接通过工厂创建就可以了。比如想要320i系列车,工厂就创建这个系列的车。
工厂方法模式(Factory Method)
为了满足客户,宝马车系列越来越多,如320i、523i等等系列,一个工厂无法创建所有的宝马系列,于是又单独分出来多个具体的工厂,每个具体工厂创建一种系列,即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象,你需要指定某个具体的工厂才能生产车出来。
抽象工厂模式(Abstract Factory)
随着客户要求越来越高,宝马车必须配置空 ...
Java类与对象1.为什么不允许从静态方法中访问非静态变量?
1.静态变量属于类本身,在类加载的时候就会分配内存,可以通过类名直接访问;
2.非静态变量属于类的对象,只有在类的对象产生时,才会分配内存,通过类的实例去访问;
3.静态方法也属于类本身,但是此时没有类的实例,内存中没有非静态变量,所以无法调用。
2.关于Object类的理解
1.什么是Object类?
Object类 是Java中所有类的基类,它是所有类的超类。在Java中,每个类都直接或间接地继承自 Object类。Object类 提供了一些通用的方法和功能,可以在所有对象上使用。
2.Object类有哪些常用的方法?
1.clone() :创建并返回对象的一个副本。
实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2.equals():用于判断两个对象是否相等。
默认情况下,该方法比较的是对象的引用是否相等,可以根据需要重写该方法来实现自定义的相等判断逻辑。
java语言规范要求equals方法具有下面的特性
1. ...
Java运算符运算符是一种特殊符号,用以表示数据的运算、赋值和比较等。
1.算术运算符
2.赋值运算符
3.关系运算符[比较运算符]
4.逻辑运算符
5.位运算符[需要二进制基础]
6.三元运算符
算术运算符算术运算符是对数值类型的变量进行运算的,在java程序中使用的非常多
面试题:
1.⭐
2.⭐
关系运算符(比较运算符)1.关系运算符的结果都是boolean型,也就是要么是true,要么是false
2.关系表达式 经常在if结构的条件中或循环结构的条件中
细节说明:
1.关系运算符的结果都是boolean型。
2.关系运算符组成的表达式,我们成为关系表达式。
3.比较运算符“= =”不能写成“=”
逻辑运算符用于连接多个条件(多个关系表达式),最终的结果也是一个boolean值。
说明逻辑运算规则:
1.a & b :& 叫逻辑与 : 规则:当a 和 b 同时为 true ,则结果为true,反之为false
2.a && b : && 叫短路与 : 规则:当 a 和 b 同时为true,则 ...
Java数据类型1.Java的几种基本数据类型(4+2+1+1)
4个整型
int
4字节
short
2字节
long
8字节
byte
1字节
byte的范围是-128~127
2个浮点类型
float
4字节
dou’b’le
8字节
1个char类型
1.char 型变量中能存储一个中文汉字吗?
在 Java 中,char 类型占 2 个字节,而且 Java 默认采用Unicode 编码,一个Unicode 码占16 位,所以一个 Unicode 码占两个字节,char 类型变量可以存储一个中文汉字
1个布尔类型
boolean
整形值和布尔值之间不能进行相互转换
2.数值类型之间的转换
无丢失
byte -> short
short -> int
char -> int
int -> long
int -> double
float -> double
有丢失
int -> float
long -> float
long -> doub ...