作的是用html5 + 一些vue , mui, 阿拉丁的一些js 融合的框架, 作的嵌套开发,不是原生页面, 作的是插件,是放在别人的app平台进行部署。
共享锁下其它用户能够并发读取,查询数据。但不能增删改数据和资源共享,加了共享锁能够继续加共享锁,不能加排他锁; 排他锁下不能加其余锁,排他锁内能够读写, 其余用户只能等当前用户锁释放掉后,才能读写; 共享锁只用于表级, 使用lock命令 ,排他锁用于行级 ,使用for update; 解锁须要dba的权限,找到当前锁的sid, 而后kill掉便可。
Spring+springmvc+mybatis 框架 , Dubbo, zookeeper, maven, log4j, redis , 经常使用的一些设计模式思想要记, socket , rocketmq , quartz , ESB, webservice
简单工厂(例如在配置文件中定义一个bean), 单例模式(能够在xml中指定使用单例仍是每次new新的实例), 适配器, 观察者模式(监听器的实现), 策略模式(定义不一样算法,根据不一样客户需求调用不一样方法), 模板方法(jdbc链接池这块,将变化的东西集中写在一个地方,而后经过传入回调给模板对象,即完成调用),
AOP切面编程, 实现原理是基于动态代理实现的。动态代理至关于中转,全部客户端的请求,我能够集中到一份方法进行处理,能够根据我本身的处理逻辑控制是否进行转接, 也至关于加强,在实际调用的过程当中,顺带执行点其余任务 ;使用场景:安全校验,事务,权限管理,日志等。 Ioc 控制反转,xml中bean的注入, 咱们须要的对象不须要本身手动去new了,全都交给spring容器进行管理,用到什么直接从spring中取就好了。
Bean的定义, 静态文件过滤, 上传下载文件配置,数据库链接池配置,事务配置,持久层配置,外包文件引入, 经常使用注解, 缓存配置:@AspectJ(注解切面, @EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持), xml中可配置bean是否单例模式使用,自定义监听器, 自定义拦截器, @Import(导入配置项), @Scheduled(配置定时任务),事务注解@Transactional
用过, xml中引入tx标签,定义事务; 项目service层使用@Transactional注解,实现事务操做,可声明只读或写; 使用拦截器配置事务;xml中定义bean, 装配spring的事务类,经过属性赋值,实现事务配置;
反射,jvm在类的编译加载过程当中,将对应的类,属性登记在册,而后反射经过在类加载运行过程当中,经过对应的类的名称或者他的一个实例对象,去找对应这个类的全部方法和属性,若是明确知道哪一个方法,还能够经过传参来执行这个方法。
@Aspect(配置切面) @Before(前置加强,都会执行) @After(后置加强,都会执行) @AfterReturning(后置加强,目标方法执行成功后才会执行) @AfterThrowing(后置加强, 抛出异常后会执行) @Around(环绕加强, 至关于前置加强和后置目标方法执行成功后会执行) @annotation(能够指定切面执行时,只要有请求就能够执行,不用指定具体的代码层级)
Concat: 字符串拼接, 或者 || Instr: 指定字符串位置 Length: 长度 Trim: 去空格 Lower: 小写 Upper:大写 Nvl: 判断空 Replace: 替换 Substr: 截取 Floor: 向下取整 To_number: To_char: To_date: Decode: 判断函数等等
对于查询频率高的字段建立索引html
索引的数目不宜太多前端
选择惟一性索引vue
尽可能使用列数据量少的索引html5
尽可能使用前缀来索引java
删除再也不使用或者不多使用的索引git
select *,可能会致使不走索引web
索引列上存在null值,可能不能走索引面试
索引列上有函数运算,致使不走索引redis
隐式类型转换致使不走索引算法
!=或者<>(不等于),可能致使不走索引
使用like, in 等, 可能致使不走索引
乐观锁适用于写比较少的状况下(多读场景); 通常多写的场景下用悲观锁就比较合适(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)
大类有iterator, collection , map ,array Iterator包括: ListIterator, Collection包括: list, set, linkedlist, arraylist,hashset, linkedhashset, treeset(使用二叉树排序), sortedset Map包括: hashmap, ConcurrentHashMap , treemap , sortedmap 自定义集合内部排序,须要实现comparable 接口
- 存储方式是以键值对存储的,怎么根据key找到对应的值的? map中有两个hash值是同样的, 怎么找到对应的value 或者key ? 存储的方式是键值对,底层是数组和链表的形式存在,实现类是Entry - 总结:HashMap的实现原理: 利用key的hashCode从新hash计算出当前对象的元素在数组中的下标 存储时,若是出现hash值相同的key,此时有两种状况。(1)若是key相同,则覆盖原始值;(2)若是key不一样(出现冲突),则将当前的key-value放入链表中 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。 理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,而后将冲突的key的对象放入链表中,一旦发现冲突就在链表中作进一步的对比。 - Jdk7,8的区别: jdk8添加了红黑树,在元素个数超过8个才会使用, jdk7中有一个内部类Entry, jdk8使用的是Node类, 使用hashmap要注意若是key存储的是对象,则必定要从新hashcode和equal方法 Map先根据key的hash值到table数组中找对应的下标,获取对应的entry, 若是一个位置存在多个entry,那么hash值确定也是相等的,遍历全部entry, 去比较entry的key值,若是与传递过来的key值相等,则返回entry对应的value值, 最后都没有找到则返回null
建立线程有4种方式: 实现runnable接口, 继承thread类, 使用线程池Executor,实现callable经过建立FutureTask类对象,这个能够自定义返回类型。 Run方法是普通的方法,有方法体,若是使用run方法,程序须要一步一步走完,才能执行下一个方法,就达不到多线程的目的,使用start方法,将线程放在等待开始调用队列中,等待cpu去调度,jvm去运行。
Less, cat, ll , la, grep , tail , curl, vi, top, telnet , rm –rf , scop , mkdir , mv , pwd ,
印象深入:有一天凌晨4点,是我作的一个xx项目关联系统上线,须要作止付和解止付接口验证操做,须要生产上经过调用个人接口验证他们的功能上线是否成功, 把我留在公司一整宿,验证完没有问题,系统验证搞得我很紧张,还担忧本身的功能出问题,结果一晚上很精神,就直接在公司打代码到早上上班,这是我第一次通宵在公司打代码到次日早上上班。 比较自豪:18年初,后端架构升级到微服务开发部署,前端架构改造使用新的框架vue, 后端是我本身看着api文档一步步搭建起来的,各个组件拆分部署也是本身弄的, 另外新架构那时候刚开始引入git, vue, 10几个java开发,还都是我最早用起来,而且抽空给他们开会作过几回技术培训。并且如今我在项目中无论是开发问题查找,业务需求仍是环境,部署问题
1.不要直接将项目总体作优化,要有确切的定位哪些确实须要优化,哪些不须要优化; 2.检查须要优化的代码部分,使用分析器来定位性能瓶颈在哪些地方; 3.常常定义一些日志在关键的地方,用来定位分析性能卡顿的代码,而且分析性能瓶颈; 4.尽可能使用基本类型来代替使用包装类型; 5.避免使用bigInteger, bigDecimal 由于占用内存过高; 6.使用日志前,判断当前日志级别是否能被显示; 7.尽量使用缓存来来避免执行耗时或频繁使用的代码片断; 8.慎用线程同步的方法; 9.尽可能使用局部变量,由于局部变量保存在栈中,方法结束就会被gc清理,速度也快, 而类变量保存在堆中,耗费内存,访问也慢; 10.建立集合尽可能指定一个初始大小; 11.尽可能在适合的场合使用单例,例如数据共享,资源并发访问等;
tps比较低的话, 找几个地方进行分析:1. 网络带宽限制;2.链接池大小资源限制(例如tomcat与数据库链接池大小限制,超过则等待);3. 数据库sql性能影响;4.硬件资源限制(内存,cpu等);5. 业务逻辑较为复杂;6. 缓存策略或配置等;7. Java编码方式问题; 使用过jmeter开多并发来测试过;
了解; 架构搭建部署有几个点须要注意: 总体敏捷度,组件拆分合理性;部署方面,模块之间耦合度; 单元测试是否方便;性能方面;开发便捷性和代码重用性;
开闭原则:开闭原则就是说对扩展开放,对修改关闭。在程序须要进行拓展的时候,不能去修改原有的代码。 针对接口编程,真对接口编程,依赖于抽象而不依赖于具体。 尽可能使用合成/聚合的方式,而不是使用继承。 一个实体应当尽可能少的与其余实体之间发生相互做用,使得系统功能模块相对独立。 使用多个隔离的接口,比使用单个接口要好。 里氏代换原则:(1)子类的能力必须大于等于父类,即父类可使用的方法,子类均可以使用。(2)返回值也是一样的道理。假设一个父类方法返回一个List,子类返回一个ArrayList,这固然能够。若是父类方法返回一个ArrayList,子类返回一个List,就说不通了。这里子类返回值的能力是比父类小的。(3)还有抛出异常的状况。任何子类方法能够声明抛出父类方法声明异常的子类。 而不能声明抛出父类没有声明的异常
1.使用synchronized修饰方法实现同步机制; 2.使用volatile修饰变量实现线程同步; 3.使用阻塞队列实现线程同步;
jdk经过发射的方式来调用 cglib 经过继承类的方式来调用,为代理类和被代理类各生成一个class,而且分配一个index方法,经过index方法直接定位要执行的方法进行调用,不用反射调用,因此效率比较高一点。
1. 生产上的话, 经过观察日志, 2. 使用性能分析工具, 与eclipse集成的几款工具,profile, jConsole, 使用cat监控工具
1. 使用jmeter工具,模拟高并发请求,观察tps 2. 或者本身使用多线程模拟高并发来观察接口压力状况
spring提供了一整套流程处理,包括业务层,数据层,事务支持等,而且提供了两大核心功能aop(面向切面,能够用来解决一些公共问题)和ioc(bean的建立和注入简化并便于维护), Springmvc主要做为控制层来实现,从请求到controller,业务处理完成后,返回视图和数据给客户端。 2)springmvc的流程: 一、 用户发送请求至前端控制器DispatcherServlet; 二、DispatcherServlet收到请求调用HandlerMapping处理器映射器; 三、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(若是有则生成)一并返回给DispatcherServlet; 四、DispatcherServlet经过HandlerAdapter处理器适配器调用处理器,执行处理器(Controller,也叫后端控制器); 五、Controller执行完成返回ModelAndView,并返回给HandlerAdapter,HandlerAdapter将结果返回给DispatcherServlet; 六、DispatcherServlet将ModelAndView传给ViewReslover视图解析器,ViewReslover解析后返回具体View给DispatcherServlet; 七、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)后返回给给客户
服务端通讯有几种方式: socket方式通讯,短链接(通讯完立马断掉),长链接(同步和异步方式) mq方式同步或者通讯 Webervice方式 Redis发布订阅
Name Server 为 producer 和 consumer 提供路由信息; Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求作好准备; 生产者(Producer); 消费者(Consumer); 2). 首先从生产者方面考虑,每条消息发送成功与否都会有一个状态对应,若是失败状态,则重发一遍便可。而且还能够日志来查询是否发送并成功存储进boker块当中; 3)从broker块分析,消息支持持久化到日志里面,即便宕机重启,未读消息仍是能够加载出来,并且broker支持主从同步,使得消息也不会丢失; 4)从消费者角度考虑,消费者自身维护一个持久化的offset,标记已经成功消费或者消费失败时,发给broker的消息下标,若是消费失败,而且borker挂掉了,那么消费者会定时重试发送动做,若是消费者和broker一块儿挂了, 那么重启后,会继续从拉去offset以前的消息到本地。 a) mq有发送日志记录,每条发送消息都有对应的消息id, 他发送给消费者时会自动判断并去重, 还有就是能够本身在业务端处理重复问题。
持久化,就是把数据写到内存中; Redis支持数据类型: list , hash , set , zset , String ; Redis有一种通信协议RESP,能够实现客户端于服务端通讯, 类型websocket ; Redis有几种架构部署模式: 单机模式: 搭建简单,内存容量有限,没法扩容 集群模式:节点之间经过数据共享, 哨兵模式:经过间隔时间监听master节点,出现master节点不可用时,会经过投票选举新的master, 节点直接数据也是经过master同步到各个节点,master写压力比较大 主从复制:有一个master主节点,多个slave从节点,数据更新的话, master都会同步到slave从节点,用来保证数据一致,没法保证高可用,master写压力比较大
一个是线程安全,一个不是线程安全的, 由于concurrentmap使用了分段锁,将map数据分红一段一段存储,而后给每一段数据加上一把锁,就实现了高并发。
乐观锁假设认为数据通常状况下不会形成冲突,因此在数据进行提交更新的时候,才会正式对数据的冲突与否进行检查,(经过对比版本号,查询的时候会带一个数据库版本号,更新的时候用来作对比) 悲观锁, 每次它去拿数据的时候都会上锁,知道锁释放,别人才能操做,不适用于高并发
final修饰类是不能被继承; final修饰对象不能在被建立; fianl修饰方法不能在子类中被覆盖; final修饰变量,称为常量,初始化之后不能改变值。
equals 一般用来比较两个对象的内容是否相等, ‘==’ 一般用来比较两个对象的地址是否相等 equals默认等同于‘==’ 若是判断一个类或对象是否相等, 若是没有重写equals方法,则判断方式就按照‘==’判断
Javabean注入有两种方式: 构造函数注入,set/get方式注入 Spring注入bean有以下几种方式: Xml注入;使用注解@Autowired; 使用java方式注入;经过构建applicationContext对象方式注入
Spring的ioc容器会进行检查,若是是经过xml中经过set属性注入, 对于不是propertype属性注入的bean,spring能够提早缓存建立的bean,若是存在就直接使用。
其实也没有什么技术难点,基本遇到的问题都能及时解决,例如sql中<,> 号,sql结尾加了;,没有写#号等等, 都能根据报错提示很快定位并进行修正。
Mybatis-generators 自动生成dao,xml,bean的反向生成插件 Mybatis-plugins 自动关联dao,xml文件,并能够检测属性值是否错误 Mybatis-pagehelper 分页插件, 是经过spring的aop实现的,能够在执行sql的时候,把相关数据在执行一遍, 将当前表做为临时表,预编译sql以后执行
Aop方式能够在xml配置中体现出来,经过配置加强来实现事务的配置; 可是还有一种比较方便的配置方式,在xml中配置一行代码tx:annotation-driven , 而后在要实现事务的方法上添加@transaction注解, 事务回滚的状况,超时,抛异常都会致使事务回滚
首先存储的时候,根据key值经过散列算法得出对应的下标,算法会尽量随机均匀的将数据分布在每一个数组下,而扩容时根据对应的算法进行实现。 https://www.cnblogs.com/williamjie/p/9358291.html
sleep方法: 属于Thread类中的方法;会致使程序暂停执行指定的时间,让出cpu该其余线程,可是他的监控状态依然保持着,当指定时间到了以后,又会自动恢复运行状态;在调用sleep方法的过程当中,线程不会释放对象锁。(只会让出CPU,不会致使锁行为的改变) wait方法: 属于Object类中的方法;在调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备。获取对象锁进入运行状态。(不只让出CPU,还释放已经占有的同步资源锁)
添加同步锁,wait则是释放当前同步锁,并让出cpu资源 https://my.oschina.net/HerrySun/blog/714156
Synchronized
1.使用volitail, 2.使用wait , nofity, 3.使用synchronized, 4.使用ThreadLocal线程变量 1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类; 2.synchronized没法判断是否获取锁的状态,Lock能够判断是否获取到锁; 3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程当中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),不然容易形成线程死锁; 4.用synchronized关键字的两个线程1和线程2,若是当前线程1得到锁,线程2线程等待。若是线程1阻塞,线程2则会一直等待下去,而Lock锁就不必定会等待下去,若是尝试获取不到锁,线程能够不用一直等待就结束了; 5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(二者皆可) 6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少许的同步问题。
Jvm将.java文件编译成..class文件,而后经过classloader类加载器将类信息加载到虚拟机内存中,在使用的时候在去建立这个对象。
高并发: 高并发是一种状态,若是大量请求访问网关接口。这种状况会发生大量执行操做,如数据库操做、资源请求、硬件占用等。这就须要对接口进行优化,而多线程是处理高并发的一种手段 多线程:是一种异步处理的一种方式,在同一时刻最大限度的利用计算机资源
核心线程数,最大线程数,线程存活时间,线程队列 好比去火车站买票, 有10个售票窗口, 但只有5个窗口对外开放. 那么对外开放的5个窗口称为核心线程数, 而最大线程数是10个窗口.若是5个窗口都被占用, 那么后来的人就必须在后面排队, 但后来售票厅人愈来愈多, 已经人满为患, 就相似于线程队列已满.这时候火车站站长下令, 把剩下的5个窗口也打开, 也就是目前已经有10个窗口同时运行. 后来又来了一批人,10个窗口也处理不过来了, 并且售票厅人已经满了, 这时候站长就下令封锁入口,不容许其余人再进来, 这就是线程异常处理策略.而线程存活时间指的是, 容许售票员休息的最长时间, 以此限制售票员偷懒的行为.
将私有线程和该线程存放的副本对象作一个映射,各个线程变量之间互不影响,不共享数据,线程安全,通常存储为静态类型,能够在其余地方进行调用
非检查异常:Error 和 RuntimeException 以及他们的子类;这样的异常多半是代码写的有问题, 数组越界,强制类型转换等。 检查异常:除了Error 和 RuntimeException 以及他们的子类以外的异常;程序自己运行环境中出现的异常,须要使用try .. catch扑捉。 - 内存溢出博文:http://outofmemory.cn/c/java-outOfMemoryError - 致使OutOfMemoryError异常的常见缘由有如下几种: 内存中加载的数据量过于庞大,如一次从数据库取出过多数据; 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收; 代码中存在死循环或循环产生过多重复的对象实体; 使用的第三方软件中的BUG; 启动参数内存值设定的太小 - 错误常见的错误提示: tomcat:java.lang.OutOfMemoryError: PermGen space tomcat:java.lang.OutOfMemoryError: Java heap space weblogic:Root cause of ServletException java.lang.OutOfMemoryError resin:java.lang.OutOfMemoryError java:java.lang.OutOfMemoryError - 须要重点排查如下几点: 检查代码中是否有死循环或递归调用。 检查是否有大循环重复产生新对象实体。 检查对数据库查询中,是否有一次得到所有数据的查询。通常来讲,若是一次取十万条记录到内存,就可能引发内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引发内存溢出。所以对于数据库查询尽可能采用分页的方式查询。 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
(1)导入dubbo、zookeeper依赖 (2)在服务提供者端,编写服务接口,服务接口的实现类,编写配置文件 (3)修改web.xml读取配置文件 (4)在服务消费者,即客户端,调用服务接口,调用服务实现类,编写配置文件 这样系统间就能够互相通讯,从而感受像在本地使用同样。
· 服务容器负责启动,加载,运行服务提供者。 · 服务提供者在启动时,向注册中心注册本身提供的服务。 · 服务消费者在启动时,向注册中心订阅本身所需的服务。 · 注册中心返回服务提供者地址列表给消费者,若是有变动,注册中心将基于长链接推送变动数据给消费者。 · 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,若是调用失败,再选另外一台调用。 · 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
枚举(Enumeration) 位集合(BitSet) 向量(Vector) 栈(Stack) 字典(Dictionary) 哈希表(Hashtable) 属性(Properties) 数组array 链表linkedList Collection Map
简单的说,就是一次大的操做由不一样的小操做组成,这些小的操做分布在不一样的服务器上,且属于不一样的应用,分布式事务须要保证这些小操做要么所有成功,要么所有失败。本质上来讲,分布式事务就是为了保证不一样数据库的数据一致性。
是由于一个是数组,一个是链表存储,数组下表具备连续性,能够经过偏移量查询,链表存储内存是不连续的,须要经过所有便利查询
一、经过类名.class方式得到,Class<?> cType = ClassName.class; 二、经过Class.forName()方法得到,Class<?> cType = Class.forName("类全名"); 三、经过对象名.getClass()方法获取,Class<?> cType3 = objName.getClass(); 总结:三种方式均可以得到Class对象,区别是方法一不执行静态块和动态构造块,方法二执行静态块、不执行动态构造块,方法三须要建立对象,静态块和动态构造块均会执行; 注意:静态块仅在类加载时执行一次,若类已加载便再也不重复执行;而动态构造块在每次new对象时均会执行
1.HashTable Map<String, String> hashtable = new Hashtable<>(); HashTable使用synchronized来保证线程安全的,全部线程竞争同一把锁,效率低 2.ConcurrentHashMap Map<String, String> concurrentHashMap = new ConcurrentHashMap<>(); 使用锁分段技术:它包含一个segment数组,将数据分段存储,给每一段数据配一把锁,效率高 Java8中使用CAS算法 3.Synchronized Map Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>()); 调用synchronizedMap()方法后会返回一个SynchronizedMap类的对象,而在SynchronizedMap类中使用了synchronized同步关键字来保证对Map的操做是安全的。
在mybatis框架中,写dao层的mapper接口时,是不能够进行方法的重载的, 重载时,会出现异常: mybatis中mapper.xml是不会准确映射到Java中的重载方法的。最好不要在mapper接口中使用方法重载。 Dao层,编译不会报错,运行会报错