JRE(Java Runtime Enviroment)是运行Java程序所必须环境的集合,包含JVM标准实现及 Java核心类库。它包括Java虚拟机、Java平台核心类和支持文件。它不包含开发工具(编译器、调试器等)。
JDK(Java Development Kit)是Java开发工具包,它提供了Java的开发环境(提供了编译器javac等工具,用于将java文件编译为class文件)和运行环境(提供了JVM和Runtime辅助包,用于解析class文件使其得到运行)。
分别是byte, short, int, long, char, float, double, boolean.
1.byte
byte属于Java中的整型,长度为1字节8bit,取值10000000(-128)到 01111111(127),变量初始化默认值为0,包装类Byte
2.short
short属于Java中的整型,长度为2字节16bit,取值10000000 00000000(-32768)到 01111111 11111111(32767),变量初始化默认值为0,包装类Short
3.int
int属于Java中的整型,长度为4字节32bit,取值-2^31 (-2,147,483,648)到 2^31-1(2,147,483,647),变量初始化默认值为0,包装类Integer
4.long
long属于Java中的整型,长度为8字节 64bit,取值-2^63 (-9,223,372,036,854,775,808)到 2^63-1(9,223,372,036,854,775,8087),变量初始化默认值为0或0L,包装类Long
5.float
float属于Java中的浮点型,也叫单精度浮点型,长度为4字节 32bit,变量初始化默认值0.0f,包装类Float,取值2-128~2128
6.double
double属于Java中的浮点型,也叫双精度浮点型,长度为8字节 64bit,变量初始化默认值0.0d,包装类Double,取值2-1024~21024
7.char
char属于java中的字符型,占2字节 16bit,可以赋值单字符以及整型数值, 变量初始化无默认值,包装类Character。
如:
char a = ‘a’;
char a = ‘中’;
char a = 12; // 取值范围0~65536,因为char类型在ASCII字符编码中,有对应的数值,可直接做运算,输出字符表中对应的字符
8.boolean
在JVM中并没有提供boolean专用的字节码指令,而boolean类型数据在经过编译后在JVM中会通过int类型来表示,此时boolean数据4字节32位,而boolean数组将会被编码成Java虚拟机的byte数组,此时每个boolean数据1字节占8bit.
仅有两个值true, false,变量初始化默认值false
对于==,一般比较的是值是否相等 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等; 如果作用于引用类型的变量,则比较的是所指向的对象的地址
对于equals方法,一般为比较内容是否相同 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址; 诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
String 被声明为 final,因此它不可被继承。(Integer 等包装类也不能被继承)
之所以设计成不可变,是为了安全,保证了线程安全,以及让常量池有意义
string不可变的设计出于性能考虑,当然背后的原理是string pool,当然string pool不可能使string类不可变,不可变的string更好的提高性能。
具体答案参考我之前的文章https://blog.csdn.net/JiaMing11_27/article/details/119078588?spm=1001.2014.3001.5501
ArrayList和LinkedList 都实现了list的接口,Al底层是数组,时间复杂度是O(1),Lk底层数据结构是双向循环链表 ,链表只有一个前驱和后继,时间复杂度O(n),
相对来说,Al是数组查找更容易,Lk因为是链表,所以插入、删除比较容易,但是更占内存,因为每一个节点存储了两个引用 ,一个指向前一个元素 一个后。
父类静态代变量 父类静态代码块 子类静态变量 子类静态代码块
父类非静态变量 父类构造函数 子类非静态变量 子类构造
1.ReentrantLock 是 API 级别的,synchronized 是 JVM 级别的
2. ReentrantLock 可以实现公平锁
3 ReentrantLock 通过 Condition 可以绑定多个条件
4. 底层实现不一样, synchronized 是同步阻塞,使用的是悲观并发策略,lock 是同步非阻塞,采用的是乐观并发策略
5. Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现。
6. synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,
因此使用 Lock 时需要在 finally 块中释放锁。
7.通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
hashMap是线程不安全的,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,采用哈希表来存储的,hashMap是根据键的hashCode值存储数据,又很快的访问速度,但是遍历顺序不确定 hashMap是一对一或一对多的关系 键只允许有一个空值 value可以有多个 当键相同时 会覆盖掉value值
底层实现原理:
HashMap4种构造方法 指定初始大小和负载因子 指定初始大小和默认负载因子 都采用默认值 容量默认16 减少hash碰撞次数 折中 均匀泊松分布 负载因子默认0.75 因为0.5 元素达到一半就扩容 扩容太浪费资源 查询效率会增加 但是空间利用率低 1.0时空间利用率高了 但是耗费时间
(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。
(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。
jvm提供的轻量级同步机制
三个特性:保证可见性 不保证原子性 禁止指令重排
在Java当中,线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
第一是创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态;
第二是就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,等待或者睡眠中回来之后,也会处于就绪状态
第三是运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
第四是阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend等方法都可以导致线程阻塞。
第五是死亡状态。如果一个线程的run方法执行结束,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪状态。
FixedThreadPool和SingleThreadExecutor => 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而引起OOM异常
CachedThreadPool => 允许创建的线程数为Integer.MAX_VALUE,可能会创建大量的线程,从而引起OOM异常,这就是为什么禁止使用Executors去创建线程池,而是推荐自己去创建ThreadPoolExecutor的原因。
JVM类加载机制定义:
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可被虚拟机直接使用的Java类型的过程
类从被加载到虚拟机内存中开始、到卸载出内存为止,整个生命周期包括七个阶段:
final:java中的关键字,修饰符。
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被声明为abstract抽象类的和final的类。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变.
1)被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。
2)被声明final的方法只能使用,不能重载。
finally:java的一种异常处理机制。
finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
finalize:Java中的一个方法名。
Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没被引用时对这个对象调用的。它是在Object类中定义的,因此所的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。
finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
String实现了三个接口:Serializable、Comparable、CarSequence
StringBuilder只实现了两个接口Serializable、CharSequence,相比之下String的实例可以通过compareTo方法进行比较,其他两个不可以。
线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。
session生成方式?
浏览器第一次访问服务器,服务器会创建一个session,然后同时为该session生成一个唯一的会话的key,也就是sessionid,然后,将sessionid及对应的session分别作为key和value保存到缓存中,也可以持久化到数据库中,然后服务器再把sessionid,以cookie的形式发送给客户端。这样浏览器下次再访问时,会直接带着cookie中的sessionid。然后服务器根据sessionid找到对应的session进行匹配;
还有一种是浏览器禁用了cookie或不支持cookie,这种可以通过URL重写的方式发到服务器;
简单来讲,用户访问的时候说他自己是张三,他骗你怎么办? 那就在服务器端保存张三的信息,给他一个id,让他下次用id访问。
token的生成方式?
答:浏览器第一次访问服务器,根据传过来的唯一标识userId,服务端会通过一些算法,如常用的HMAC-SHA256算法,然后加一个密钥,生成一个token,然后通过BASE64编码一下之后将这个token发送给客户端;客户端将token保存起来,下次请求时,带着token,服务器收到请求后,然后会用相同的算法和密钥去验证token,如果通过,执行业务操作,不通过,返回不通过信息;
线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。
具体答案参考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651072?spm=1001.2014.3001.5501
具体答案参考之前博客https://blog.csdn.net/JiaMing11_27/article/details/119651846?spm=1001.2014.3001.5501
答案看我之前博客https://blog.csdn.net/JiaMing11_27/article/details/118436439?spm=1001.2014.3001.5501
进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。
进程状态:
一般来说,进程有三个状态,即就绪状态,运行状态,阻塞状态
程序至少有一个进程,进程至少有一个线程
线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
1、输入网址
2、DNS解析
3、建立tcp连接
4、客户端发送HTTP请求
5、服务器处理请求
6、服务器响应请求
7、浏览器展示HTML
8、浏览器发送请求获取其他在HTML中的资源。
吞吐量优先和响应优先的垃圾收集器选择。
Cms是以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现。比较占用cpu资源,切易造成碎片。
G1是面向服务端的垃圾收集器,是jdk9默认的收集器,基于标记-整理算法实现。可利用多核、多cpu,保留分代,实现可预测停顿,可控。
参考之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119044707?spm=1001.2014.3001.5501
1. 使用delete 语句
特点:
delete 属于数据库操纵语言DML,表示删除表中的数据,删除过程是每次从表中删除一行,并把该行删除操作作为事务记录在日志中保存
可以配合事件(transaction)和 回滚(rollback)找回数据,且自增不会被重置
delete 既可以对table也可以对view
可以全部删除,也可以按条件删除
2. 使用truncate 语句
特点:
3.使用drop语句
特点:
多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题*存在问题:
1.脏读:一个事务,读取到另一个事务中没有提交的数据
2.不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
3,幻读:一个事务操作(DNL)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
隔离级别:
教据库查询隔离级别:
select @@tx_isolation;
数据库设置隔离级别:
set global transaction isolation level级别字符串;
数组静态分配内存,链表动态分配内存;数组在内存中连续,链表不连续;数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。
数组优点:
随机访问性强(通过下标进行快速定位)
查找速度快
数组缺点:
插入和删除效率低(插入和删除需要移动数据)
可能浪费内存(因为是连续的,所以每次申请数组之前必须规定数组的大小,如果大小不合理,则可能会浪费内存)
内存空间要求高,必须有足够的连续内存空间。
数组大小固定,不能动态拓展
链表的优点
插入删除速度快(因为有next指针指向其下一个节点,通过改变指针的指向可以方便的增加删除元素)
内存利用率高,不会浪费内存(可以使用内存中细小的不连续空间(大于node节点的大小),并且在需要空间的时候才创建空间)
大小没有固定,拓展很灵活。
链表的缺点
不能随机查找,必须从第一个开始遍历,查找效率低
单链表:
双链表:
为什么市场上单链表的使用多于双链表呢?
从存储结构来看,每个双链表的节点要比单链表的节点多一个指针,而长度为n就需要
n*length(这个指针的length在32位系统中是4字节,在64位系统中是8个字节)
的空间,这在一些追求时间效率不高应用下并不适应,因为它占用空间大于单链表所占用的空间;这时设计者就会采用以时间换空间的做法,这时一种工程总体上的衡量。
参考我之前博客:https://blog.csdn.net/JiaMing11_27/article/details/119141032?spm=1001.2014.3001.5501
参考博客:https://blog.csdn.net/JiaMing11_27/article/details/116609811?spm=1001.2014.3001.5501
参考博客:https://blog.csdn.net/JiaMing11_27/article/details/116610872?spm=1001.2014.3001.5501
1、@SpringBootApplication
包含@Configuration、@EnableAutoConfiguration、@ComponentScan
通常用在主类上。
2、@Repository
用于标注数据访问组件,即DAO组件。
3、@Service
用于标注业务层组件。
4、@RestController
用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody
5、@ResponseBody
表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,加上@responsebody后返回结果不会被解析
为跳转路径,而是直接写入HTTP response body中。比如异步获取json数据,加上@responsebody后,会直接返回json数据。
6、@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
7、@ComponentScan
组件扫描。相当于,如果扫描到有@Component @Controller @Service等这些注解的类,则把
这些类注册为bean。
8、@Configuration
指出该类是 Bean 配置的信息源,相当于XML中的,一般加在主类上。
9、@Bean
相当于XML中的,放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理。
10、@EnableAutoConfiguration
让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。
11、@AutoWired
byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
当加上(required=false)时,就算找不到bean也不报错。
12、@Qualifier
当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用
13、@Resource(name=“name”,type=“type”)
没有括号内内容的话,默认byName。与@Autowired干类似的事。
14、@RequestMapping
RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
以上来自W3cSchool
ThreadLocal主要为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。一个线程可以储存多个ThreadLocal的值
key使用软引用解决了ThreadLocal对象本身的内存泄漏问题,使用remove方法解决了Entry的value的内存泄漏问题。
Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
Bean实例化后对将Bean的引入和值注入到Bean的属性中
如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。
#{} 这种取值是编译好SQL语句再取值
${} 这种是取值以后再去编译SQL语句
#{}方式能够很大程度防止sql注入。
$方式无法防止Sql注入。
KaTeX parse error: Expected 'EOF', got '#' at position 27: …对象,例如传入表名. 一般能用#̲的就别用.
Nginx是一个http服务器。是一个使用c语言开发的高性能的http服务器及反向代理服务器。Nginx是一款高性能的http
服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师IgorSysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。
1、 http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。 2、 虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。 3、 反向代理,负载均衡。 当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。
持续更新!!!
时间匆忙,如果有错误欢迎指出,有什么缺少的也可以私信我,我会及时补充
创作不易,点个赞再走吧,你的支持是我创作的最大动力,谢谢!