常识+Java+mysql
常识
1.进程线程区别:
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
原文链接:https://blog.youkuaiyun.com/kuangsonghan/article/details/80674777
2.死锁:
互斥条件:一个资源每次只能被一个进程使用,即在一段时间内某 资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源 已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
不可剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能 由获得该资源的进程自己来释放(只能是主动释放)。
循环等待条件: 若干进程间形成首尾相接循环等待资源的关系
银行家算法:
银行家算法:资源P1申请资源,银行家算法先试探的分配给它(当然先要看看当前资源池中的资源数量够不够),若申请的资源数量小于等于Available,然后接着判断分配给P1后剩余的资源,能不能使进程队列的某个进程执行完毕,若没有进程可执行完毕,则系统处于不安全状态(即此时没有一个进程能够完成并释放资源,随时间推移,系统终将处于死锁状态)。
当一个进程申请使用资源的时候,银行家算法通过先 试探 分配给该进程资源,然后通过安全性算法判断分配后的系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待。
原文链接:https://blog.youkuaiyun.com/qq_33414271/article/details/80245715
3.Get post请求:
- GET 请求可被缓存
- GET 请求保留在浏览器历史记录中
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET 请求有长度限制
- GET 请求只应当用于取回数据
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求刷新没有反应,POST会重新提交表单
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
https://www.cnblogs.com/logsharing/p/8448446.html
4.RPC&&REST ful
建议系统内部使用rpc,对外服务使用rest
RESTful架构:(spark可以通过REST API实现对集群对监控)
(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层,比如用JSON,XML,JPEG等;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
基于http,效率低一些,灵活度更高
rest: https://www.zhihu.com/question/27785028/answer/48096396
RPC:ipc(进程间通信)的一种,另一种是lpc,在本地之间的进程通信
- RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。
- RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯) RPC 是一个请求响应模型。
- 客户端发起请求,服务器返回响应(类似于Http的工作方式) RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。
一般使用过tcp,也有http的,性能高一些。RPC 框架作为架构微服务化的基础组件,它能大大降低架构微服务化的成本,提高调用方与服务提供方的研发效率,屏蔽跨进程调用函数(服务)的各类复杂细节。让调用方感觉就像调用本地函数一样调用远端函数、让服务提供方感觉就像实现一个本地函数一样来实现服务。
rpc:https://www.jianshu.com/p/b0343bfd216e
Java
1.内存溢出(oom)
- 堆溢出:堆空间无法给新的对象分配内存空间且GC一次后仍然无法分配足够的空间时会导致堆溢出。
- 栈溢出:这是由于线程请求的栈深度大于虚拟机所允许的最大深度,无法压入新的栈帧,这时可以检查一下代码中是否存在死循环的递归调用。无法创建新线程也是因为栈空间不足的原因。
- 方法区溢出:这里还可以分为运行时常量池溢出和方法区存放Class过多导致溢出。过去的话方法区的大小是设定好的,Java8之后将Class信息放到了元空间,并且元空间是可以动态申请扩展的。
- 元空间不足:太多类或太大类加载到元空间
- gc超过限度:gc发现效率不高。默认情况下,当应用程序花费超过98%的时间用来做GC并且回收了不到2%的堆内存时,会抛出java.lang.OutOfMemoryError:GC overhead limit exceeded错误。具体的表现就是你的应用几乎耗尽所有可用内存,并且GC多次均未能清理干净。
- 交换空间耗尽
- 程序试图分配大于jvm可以支持的数组。
内存泄露达一定程度会引发oom
内存泄漏是指编写的代码中含有bug,不是指会引发程序执行结果错误那种,而是不可达的对象停留在堆中,即代码中含有对象的强引用没有没释放掉,导致该无用的对象无法被垃圾收集器收集。
假设内存足够大,而内存泄漏的情况并不严重,只要还有足够的空间分配给新的对象,那样即使内存泄漏也不会引发OOM。
如:静态集合类,各种连接,如数据库连接,没有调用close
2.gc
minor gc触发条件:当Eden区满时,触发Minor GC。
Full gc:
System.gc()
老年代空间不足
方法区空间不足
https://blog.youkuaiyun.com/weixin_39788856/article/details/80388002
3.start和run的区别
1)start() 会创建新的栈空间并且会产生新的子线程(工作线程),线程的启动者
2)run()调用线程对象中的run方法且不会产生新的线程,是在主线程中执行的,线程的任务执行者
4.双亲委托的优势:避免重复加载 + 避免核心类篡改
5.线程状态
NEW
至今尚未启动的线程处于这种状态。
RUNNABLE
正在 Java 虚拟机中执行的线程处于这种状态。
BLOCKED
受阻塞并等待某个监视器锁的线程处于这种状态。
WAITING
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。
TIMED_WAITING
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。
TERMINATED
已退出的线程处于这种状态。
原文链接:https://blog.youkuaiyun.com/biglogo/article/details/79261745
ThreadLocal的一个典型使用场景,其实就是在“同一个线程内”为了避免多个方法调用过程中传递参数的麻烦,把一些上下文数据放到线程的ThreadLocalMap中,在需要使用这些参数的地方,直接从ThreadLocalMap中获取即可。
理解是线程间不同步,线程内方法同步。
6.lock和synchronize:
1)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个接口,通过这个类可以实现同步访问;
2)Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
Synchronize是重入锁
在Java中,synchronized就不是可中断锁,而Lock是可中断锁。
抽象类与接口:
1)抽象类则可以包含普通方法,接口中的普通方法默认为抽象方法。
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的,并且必须赋值,否则通不过编译。
3)接口不能包含构造器,抽象类可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
4)接口里不能包含初始化块,但抽象类里完全可以包含初始化块。
5)就是我们所说的单继承多实现了。
泛型:
意义:类型的参数化,就是可以把类型像方法的参数那样传递。。
泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。
- 1.泛型可以使程序的操作更加安全,可以避免发生类型转换异常。
- 2.在程序中如果使用类时没有指定泛型,则泛型将被擦除掉,将使用Object接收参数。
- 3.可以使用通配符“?”接收全部泛型对象。
- 4.通过<?extends 类>可以设置泛型的上限,通过<? super 类>可以设置泛型的下限。
- 上边界类型通配符(<? extends 父类型>):因为可以确定父类型,所以可以以父类型去获取数据(向上转型)。但是不能写入数据。取时相当于父类(向上转型)
- 下边界类型通配符(<? super 子类型>):因为可以确定最小类型,所以可以以最小类型去写入数据(向上转型)。而不能获取数据。取时相当于object,也是向上转型
- 无边界类型通配符(<?>) 等同于上边界通配符<? extends Object>,所以可以以Object类去获取数据,但意义不大。
- 5.泛型方法可以定义在泛型类中,也可以定义在普通类中。
- 6.泛型可以在接口中定义,实现泛型接口的子类要指明具体的泛型类型。
- 7.泛型可以嵌套使用。*在程序中定义没有方法的接口,这样的接口一般称为标识接口。
原文链接:https://blog.youkuaiyun.com/lijizhi19950123/article/details/78022820
mysql:
1.事务
事务的隔离级别:
- SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
- {
- READ UNCOMMITTED
- | READ COMMITTED
- | REPEATABLE READ
- | SERIALIZABLE
- }
global是全局,将所有的transaction默认配置设置成和此次事物级别一样
session为此次访问,不影响别人的。
https://www.cnblogs.com/shihaiming/p/11044740.html
事务的基本要素(ACID)
1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
mysql默认的事务隔离级别为repeatable-read
索引为什么要用B+树:https://www.cnblogs.com/tiancai/p/9024351.html
理解就是为了增加便利效率,使用了b树,将树变矮,减少了io读取。但是数据库中遍历或者范围搜索很常见,通过b+树可以直接通过叶子结点实现遍历。其次,因为b+树在非叶子结点中不存放数据,所以一次可以读取更多的索引,从而又减少了io读取的次数。