因为细节内容实在太多啦,因此只把部分知识点整理出来粗略的介绍,每一个小节点里面都有更细化的内容!
接下来开始分享啦java
先后端分离:node
补充:spring
注:这个“仓库”应该就是本地安装maven的目录下的Repository的文件夹
线程锁:当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效,由于线程锁的实如今根本上是依靠线程之间共享内存实现的。如synchronizedsql
进程锁:为了控制同一操做系统中多个进程访问某个共享资源。数据库
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。后端
分布式锁通常有三种实现方式:数组
乐观锁的实现:使用版本标识来肯定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时能够采起丢弃和再次尝试的策略。浏览器
分布式锁基于Redis的实现:(本系统锁采用的)缓存
基本命令:安全
加锁方式:
这里的jedis是Java对Redis的集成
jedis.set(String key, String value, String nxxx, String expx, int time)
错误的加锁方式1:
若是程序在执行完setnx()以后忽然崩溃,致使锁没有设置过时时间。那么将会发生死锁。
Long result = jedis.setnx(Key, value); if (result == 1) { // 若在这里程序忽然崩溃,则没法设置过时时间,将发生死锁 jedis.expire(Key, expireTime); }
错误的加锁方式2:
分布式锁采用(Key,过时时间)的方式,若是锁存在,那么获取它的过时时间,若是锁的确已通过期了,那么得到锁,而且设置新的过时时间
错误分析:不一样的客户端之间须要同步好时间。
//+V:BGM7756,免费领取资料long expires = System.currentTimeMillis() + expireTime; String expiresStr = String.valueOf(expires); // 若是当前锁不存在,返回加锁成功 if (jedis.setnx(lockKey, expiresStr) == 1) { return true; } // 若是锁存在,获取锁的过时时间 String currentValueStr = jedis.get(lockKey); if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { // 锁已过时,获取上一个锁的过时时间,并设置如今锁的过时时间 String oldValueStr = jedis.getSet(lockKey, expiresStr); if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { // 考虑多线程并发的状况,只有一个线程的设置值和当前值相同,它才有权利加锁 return true; } } // 其余状况,一概返回加锁失败 return false; //+V:BGM7756,免费领取资料
中场休息时间!最近整理了一份Java核心知识点。覆盖了springboot、JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。
若是须要免费获取到这个【资料】文档的话添加微信:BGM7756
解锁:判断锁的拥有者后可使用 jedis.del(lockKey) 来释放锁。
分布式锁基于Zookeeper的实现
Zookeeper简介:Zookeeper提供一个多层级的节点命名空间(节点称为znode),每一个节点都用一个以斜杠(/)分隔的路径表示,并且每一个节点都有父节点(根节点除外)。
例如,/foo/doo这个表示一个znode,它的父节点为/foo,父父节点为/,而/为根节点没有父节点。
client不论链接到哪一个Server,展现给它都是同一个视图,这是zookeeper最重要的性能。
Zookeeper 的核心是原的广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫作Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步之后,恢复模式就结束了。状态同步保证了leader和Server具备相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务,实现中zxid是一个64位的数字。
Zookeeper的分布式锁原理
获取分布式锁的流程:
个人解释:
A在Locker下建立了Node_n —>循环 ( 每次获取Locker下的全部子节点 —> 对这些节点按节点自增号排序顺序 —> 判断本身建立的Node_n是不是第一个节点 —> 若是是则得到了分布式锁 —> 若是不是监听上一个节点Node_n-1 等它释放掉分布式锁。)
@ControllerAdvice处理全局异常Mybatis注解方式的使用:
@insert 用注解方式写SQL语句
一、分布式系统:多节点,节点发送数据交互,不共享主内存,但经过网络发送消息合做。
分布式:不一样功能模块的节点
集群:相同功能的节点
二、Session 与token
服务端在HTTP头里设置SessionID而客户端将其保存在cookie
而使用Token时须要手动在HTTP头里设置,服务器收到请求后取出cookie进行验证。
都是一个用户一个标志
三、分布式系统中的Session问题:
高并发:经过设计保证系统可以同时并行处理不少请求。
当高并发量的请求到达服务端的时候经过负载均衡的方式分发到集群中的某个服务器,这样就有可能致使同一个用户的屡次请求被分发到集群的不一样服务器上,就会出现取不到session数据的状况。
根据访问不一样的URL,负载到不一样的服务器上去
三台机器,A1部署类目,A2部署商品,A3部署单服务
通用方案:用Redis保存Session信息,服务器须要时都去找Redis要。登陆时保存好key-value,登出时让他失效
垂直扩展:IP哈希 IP的哈希值相同的访问同一台服务器
session的一致性:只要用户不重启浏览器,每次http短链接请求,理论上服务端都能定位到session,保持会话。
高并发:经过设计保证系统可以同时并行处理不少请求。(系统学习并发知识,能够在Java知音公众号回复“多线程聚合”)
同步:Java中的同步指的是经过人为的控制和调度,保证共享资源的多线程访问成为线程安全。
线程的Block状态:
a.调用join()和sleep()方法,sleep()时间结束或被打断
b.wait(),使该线程处于等待池,直到notify()/notifyAll():不释放资源
此外,在runnable状态的线程是处于被调度的线程,Thread类中的yield方法可让一个running状态的线程转入runnable。
Q:为何wait,notify和notifyAll必须与synchronized一块儿使用?Obj.wait()、Obj.notify必须在synchronized(Obj){…}语句块内。
A:wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。
Q:Synchronized:
A:Synchronized就是非公平锁,它没法保证等待的线程获取锁的顺序。
公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点Node的值就是每个请求当前锁的线程。公平锁则在于每次都是依次从队首取值。
ReentrantLock重要性:
重入锁能够看这两篇文章,都比较简单
https://www.jianshu.com/p/587...
Spring + Redis缓存的两个重要注解:
对数据库加锁(乐观锁 与 悲观锁)
悲观锁依赖数据库实现:
select * from account where name=”Erica” for update
这条sql 语句锁定了account 表中全部符合检索条件(name=”Erica”)的记录,使该记录在修改期间其它线程不得占有。
代码层加锁:
String hql ="from TUser as user where user.name='Erica'";Query query = session.createQuery(hql);query.setLockMode("user",LockMode.UPGRADE); //加锁List userList = query.list();//执行查询,获取数据
@Data 相似于自动生成了Getter()、Setter()、ToString()等方法。
JAVA1.8的新特性StreamAPI:Collectors中提供了将流中的元素累积到汇聚结果的各类方式
List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())
For - each 写法:
for each语句是java5新增,在遍历数组、集合的时候,for each拥有不错的性能。
public static void main(String[] args) { String[] names = {"beibei", "jingjing"}; for (String name : names) { System.out.println(name); } }
for each虽然能遍历数组或者集合,可是只能用来遍历,没法在遍历的过程当中对数组或者集合进行修改。
BindingResult:一个@Valid的参数后必须紧挨着一个BindingResult 参数,不然spring会在校验不经过时直接抛出异常。
@Datapublic class OrderForm { @NotEmpty(message = "姓名必填") private String name;}
后台:
//+V:BGM7756,免费领取资料@RequestMapping("save") public String save( @Valid OrderForm order,BindingResult result) { // if(result.hasErrors()){ List<ObjectError> ls=result.getAllErrors(); for (int i = 0; i < ls.size(); i++) { log.error("参数不正确,OrderForm={}", order); throw new SellException( ………… , result.getFeildError.getDefaultMessage() ) System.out.println("error:"+ls.get(i)); } } return "adduser"; } //+V:BGM7756,免费领取资料
result.getFeildError.getDefaultMessage()可抛出“姓名必填” 的异常。
四、List转为Map
//+V:BGM7756,免费领取资料public class Apple { private Integer id; private String name; private BigDecimal money; private Integer num; /*构造函数*/}List<Apple> appleList = new ArrayList<>();//存放apple对象集合Apple apple1 = new Apple(1,"苹果1",new BigDecimal("3.25"),10);Apple apple12 = new Apple(1,"苹果2",new BigDecimal("1.35"),20);Apple apple2 = new Apple(2,"香蕉",new BigDecimal("2.89"),30);Apple apple3 = new Apple(3,"荔枝",new BigDecimal("9.99"),40);appleList.add(apple1);appleList.add(apple12);appleList.add(apple2);appleList.add(apple3);Map<Integer, Apple> appleMap =appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1)); //+V:BGM7756,免费领取资料
五、Collection的子类:List、Set
List:ArrayList、LinkedList 、Vector
List:有序容器,容许null元素,容许重复元素
Set:元素是无序的,不容许元素
最流行的是基于 HashMap 实现的 HashSet,由hashCode()和equals()保证元素的惟一性。
能够用set帮助去掉List中的重复元素,set的构造方法的参数能够是List,构造后是一个去重的set。
HashMap的补充:它不是Collection下的
Map可使用containsKey()/containsValue()来检查其中是否含有某个key/value。
HashMap会利用对象的hashCode来快速找到key。
插入过程:经过一个hash函数肯定Entry的插入位置index=hash(key),可是数组的长度有限,可能会发生index冲突,当发生了冲突时,会使用头插法,即为新来的Entry指向旧的Entry,成为一个链表。
每次插入时依次遍历它的index下的单链表,若是存在Key一致的节点,那么直接替换,而且返回新的值。
可是单链表不会一直增长元素,当元素个数超过8个时,会尝试将单链表转化为红黑树存储。
为什么加载因子默认为0.75?(0.75开始扩容)
答:经过源码里的javadoc注释看到,元素在哈希表中分布的桶频率服从参数为0.5的泊松分布。
经过上面的介绍,相信你们对springboot微信点餐开源系统方面有了进一步的认识,但愿可以帮助到你们!因为细节内容实在太多啦,因此只把部分知识点整理出来粗略的介绍
最近整理了一份Java核心知识点。覆盖了springboot、JVM、锁、并发、Java反射、Spring
原理、微服务、Zookeeper、数据库、数据结构等大量知识点。