sql问题
1.学生成绩表结果如下,写一段sql取每科成绩前三名的学生。
CREATE TABLE `score` ( `id` int(10) NOT NULL AUTO_INCREMENT, `subject_id` int(10) DEFAULT NULL, `student_id` int(10) DEFAULT NULL, `score` float DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
答案1:
select id,subject_id,student_id,score from score e1 where ( select count(1) from score e2 where e2.subject_id=e1.subject_id and e2.score>=e1.score ) <=3 /*这里的数值表示你想取前几名*/ order by subject_id, score desc;
答案2:
select a.id,a.subject_id,a.student_id,a.scorefrom score a LEFT JOIN score bon a.subject_id = b.subject_idwhere a.score <= b.scoregroup by a.subject_id,a.student_id,a.scorehaving count(a.student_id) <=2order by a.subject_id,a.score desc;
2. left join的条件写在on和where的区别是什么?
数据库在连接两张或多张表的过程中,都会生成一张中间的临时表,再将临时表返回。
a、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左表的数据; b、where条件是在临时表生成好后,再对临时表进行筛选过滤的条件; c、写在on中是作为关联条件之一,但是写在where中是作为筛选条件之一;
大数据
1.简述mapreduce的shuffle过程
a、MapReduce中map阶段处理的数据传输给reduce阶段的过程称为shuffle过程
b、shuffle过程的核心就是数据分区、排序、缓存,具体就是将maptask产生的结果处理数据,分发给reducetask,并在分发的过程中,对数据按key进行分区和排序,确保reduce收到的输入数据是根据key排过序的。 c、详细的流程 1.maptask收集map输出的kv对,缓存在内存缓冲区中 2.从内存缓冲区中不断溢出本地磁盘文件,可能会溢出多个文件 3.将溢出的文件合并成大的溢出文件 4.合并过程中调用partitioner进行分区和针对key进行排序 5.reducetask根据自己的分区号去maptask机器上取相应分区的结果数据 6.reducetask会取到同一区的来自不同maptask的结果文件,reducetask对这些结果文件再进行合并(归并排序) 7.合并成大文件后,shuffle过程结束,进行reduce逻辑运算处理。 d、流程示意图2.MapReduce程序的数据倾斜问题
造成数据倾斜的原因
a.key分布不均衡,有的则过于集中。倾斜在reduce阶段 b.datanode上数据分布不均衡。倾斜在map阶段。datanode上的数据量大的当然执行的时间要长,数据量小的则执行时间短数据倾斜一般的解决方案 a.增加reduce 的jvm内存 b.增加reduce 个数 c.customer partition d.其他优化的讨论Java
1.HashMap的理解,底层基本实现,是否线程安全,如果解决碰撞问题?
hashmap底层是一个链表,链表中的每一个元素是一个table数组,链表+数组的实现。根据hash算法计key-value的存储位置,hashmap线程不安全,hashtable线程安全,hashtable里面添加了synchronized来保证线程安全,hashmap可以使用null作为key,hashtable不可以,hashmap的冲突解决方案:链表法和开放地址法。两个关键因素:加载因子和初始容量 2.ConcurrentHashMap? 采用了分段锁的方式,相比于整个map加锁,分段锁提高了并发环境下的处理能力。 3.JVM内存模型,老年代和新生代比例,YGC和FGC发生的具体场景,简单类加载过程,里面执行了哪些操作? 需要掌握的内容: 1).对象存活还是死亡的算法 计数算法和可达性算法 2).常见的垃圾回收算法 复制算法、分代收集算法 3).以及常见垃圾回收算法的特点 内存模型由方法区、堆、栈、本地方法栈、程序计数器组成。 堆划分为新生代、老年代和永久代,新生代又被划分为Eden区和survivor区。 新生代和老年代采用不同的算法,minor-gc发生在新生代,采用复制算法、full-gc发生在老年代,采用标记-清除算法 4.http协议,get和post基本区别,tcp/ip协议,三次握手? 请求的数据的放置位置不同、传输数据的大小不同、安全性不同。 5.mysql存储引擎有那些?悲观锁和乐观锁的使用场景?分布式集群实现原理? 6.springmvc和mybatis的工作原理 7.redis存储类型、事务、使用场景 8.分布式事务和分布式锁 9.dubbo超时重试,超时时间设置? 超时时间通过timeout="5000"参数配置,超时重试通过retries参数配置。 10.zookeeper作用? 11.mybatis如何分页、mysql如何分页? 12.io和nio的区别。 13.分布式session一致性 14.项目架构图 15.treemap、volatile关键字spring
ioc:依赖反转,就是将原本程序中手动创建对象的控制权,交由spring容器去管理,被反转到了spring框架 di:依赖注入,spring在创建bean对象时,动态的将依赖对象注入到bean中组件 面向接口编程:程序的扩展和维护 2.beanfactory和applicationcontext什么区别 applicationcontext继承beanfactory,spring核心工厂是beanfactory,采取延迟加载,第一次genBean时才会初始化bean ,applicationcontext是在加载配置文件的时候初始化bean 开发中一般使用applicationcontext、 3.spring bean实例化的方式 4、spring 中bean的生命周期 定义:在配置文件中用<bean></bean>定义 初始化: 5.spring如何解决线程并发问题 使用Threadlocal,Threadlocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题 Threadlocal是为每一个线程提供一个变量副本,从而隔离了多线程对变量的访问冲突 可以持有任何类型的对象。 同步机制:时间换空间 Threadlocal:空间换时间 6.spring的事物管理 事务就是对一系列的数据库操作进行统一的提交和回滚。这样可以防止脏数据。 spring也有自己的事务管理机制,一般用过transactionmanager进行管理。 spring事务提供了两类:编程式事务和声明式事务,围绕动态代理能够自动的提交和回滚事务。 事务传播特性: required 没有新建,有使用 required_new 新建事务,有挂起 support 7.aop中的几个名词 aspect joinpoint advice pointcut target object weaving aop:使用CGLIB代理或者jdk的动态代理8.spring用到的设计模式
代理模式:AOP和remoating 单例模式:spring配置文件中定义的bean默认为单例模式 模板方法:解决代码重复的问题,如restTemplate 前端控制器:spring提供了dispatchServlet对请求进行分发 工厂模式:beanFactory用来创建对象的实例9.spring等框架的web项目在tomcat项目中的启动流程
1).tomcat根据web.xml来启动,先到web.xml 2).web.xml中负责启动spring和springmvc,springmvc通过DispatchServlet启动 spring通过contextLoadlistener启动 3).配置文件中spring对一些orm框架的启动,包括mybatis,基本用过sqlsessionFactory bean来启动 并配置各种bean到ioc容器中。 通过注解和用过scan package的方式,将注解的类注册到ioc容器中。 web.xml中节点的加载顺序: listener>filter>servlet10.aop详解:
主要用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志。 关键在于aop创建的aop代理,分为静态代理(aspectj)和动态代理(spring aop) 静态代理是指在编译时期生成aop代理类, 2)所谓的动态代理就是spring框架不会去修改字节码,而是在内存中临时为方法生成一个aop对象,这个对象 包含了目标对象的所有方法,并且在特定的切面做增强处理,并且回调原对象的方法 3)动态代理两种方式:jdk动态代理和cglib代理,jdk动态代理通过反射接受被代理的类,并且要求被代理的类必须实现一个接口 核心是InvocationHandle的invoke方法,如果目标类没有实现接口,则使用cglib代理,cglib是通过继承的方式做的代理,jvm、类加载器、多线程编程、网络、io、设计模式
1.jvm内存模型和回收算法
1)栈中存放的是基本数据类型和引用,堆中存放的是各种对象实例。通过xss设置栈大小,堆的参数设置为xmx和xms 2)回收算法: 标记清除--优点减少停顿时间,缺点会造成内存碎片 复制算法--不涉及对象的删除,只是把可用的对象从一个地方复制到另一个地方,适合大量对象回收的场景,比如新生代回收 标记整理--可以解决内存碎片问题,但是会增加停顿时间分代收集:前面几种的合体,目前jvm主要采用的一种,思想就是把jvm分成不同的区域,每种区域采取不同的回收算法
将堆分为三个区域:新生代(eden+survivor0+survivor1)、老年代、永久代 新生代:存放新创建的对象,采用的复制回收算法,在s0和s1之间复制一定次数后,转移到年老代中,垃圾回收为minorGC 年老代:垃圾回收的频率较低多线程编程:
Java并发技术体系 并发工具包 concurrentHashMap ConcurrentBlockingQueue 并发工具类 future 并发接口: future executor ThreadPoolExecutor SchedulePoolExecutor Callable 进程:每个进程都有独立的代码和数据空间,进程间的切换会有较大的开销,资源分配的最小单位 线程:同一类线程共享代码和数据空间,每个线程拥有独立的线程栈和程序计数器,线程切换开销小,cpu调度的最小单位 runnable接口比thread的优势 1.避免Java中的单继承 2.增加程序的健壮性,代码可以被多个线程共享,代码和数据独立 3.线程池只能放入实现runnable或callable接口的类,不能直接放入继承thread的类 4.适合多个相同的程序代码的线程处理同一个资源。volatile和synchronized
volatile保证了线程之间变量的可见性,但是不保证原子性 synchronized保证原子性和可见性 threadLocal通过map实现,提高一个线程的局部变量,访问某个线程拥有自己的局部变量线程池
通过executors提供四种线程池 1.newFixedThreadPool 2.newCacheThreadPool 3.newScheduleThreadPool 4.newSingleThreadExecutorhttp状态码:
2xx:表示请求成功,成功处理了请求的状态代码 200:请求成功,请求希望的响应头和数据体将随即返回 201 已创建 请求成功,并且服务器创建了新的资源 202 已接收,但是服务器尚未处理 203 非授权信息 服务器成功接收请求,但响应的信息可能来自另一来源 204 无内容 205 重置内容 206 部分内容 3xx:请求被重定向,标识要完成请求需要进一步操作 300:多种选择 301:永久移动 资源被永久移动到新的位置,对该资源的访问都应该使用本响应返回的url上 302 临时移动 303 查看其他位置 304 未修改 自从上一次请求后,网页未被修改过 305 使用代理 请求者只能通过代理访问请求的页面 307 临时重定向 4xx:请求错误,请求可能出错,妨碍了服务器的处理 400 错误请求 服务器不理解的请求 401 未授权 请求要求身份验证 403 禁止 服务器拒绝请求 404 未找到 资源找不到 408 请求超时 409 请求冲突 410 已删除 请求的资源已被永久删除 5xx:服务器错误 服务器在处理请求时,发生内部错误 500 服务内部错误 502 错误的网关 503 服务不可用 505 http版本不支持
1.接口幂等性概念
2.synchronized和lock的区别 Thread的一些方法: join:调用该方法等待线程结束 sleep:调用该方法该线程进入等待状态 wait和notify是object的方法,标识线程挂起和恢复。 区别: 锁的释放:synchronized是已获取锁的线程执行完同步代码,释放锁;线程执行发生异常,jvm会自动释放锁。 lock需要手动释放锁。 锁的获取:互斥获得, 锁状态:synchronized无法判断,lock可以判断 lock的几个方法: lock:获取锁 unLock():释放锁 trylock():返回boolean值,判断是否可以获得锁 tryLock(Long time,Unit): lockInterruptly(); 底层实现方式: synchronized:java是通过字节码指令控制程序(monitorenter、monitorexit),当线程执行遇到monitorenter时 就会尝试获取锁,如果获得锁那么锁计数+1,如果没有,那么阻塞。当遇到monitorexit时释放锁。计数器-1. lock:底层实际是CAS乐观锁的体现,基于jdk实现的接口,和虚拟机层面不是一个概念。 lock(interface)-》实现reentrantLock readWriteLock(interface)-》实现reentrantReadWriteLock。 开发中常见的reentrantLock 和reentrantReadWriteLock.3.那些设计模式,如何应用的
工厂方法: 抽象工厂: 单例: 策略模式: 1.equals和==的区别 jvm内存分配,栈内存和堆内存 当创建一个对象时,会调用他的构造函数来开辟空间,将对象数据存储到对内存中, 同时,在栈内存中生成对应的引用。 ==比较的是变量(栈内存)中存放的对象的物理内存(堆内存)地址 equals比较的是两个对象的内容是否一致。 2.各种锁,synchronized和lock的区别 独享锁:一次只能被一个线程持有 共享锁:一次可以被多个线程持有 互斥锁:reentrantLock 读写锁:readwriteLock 分段锁:concurrentHashMap并发的实现就是通过分段锁的方式来实现高效的并发操作 称为segment,类似于hashmap的结构,即内部拥有一个entry数组,数组中每个元素又是一个 链表。同时又是一个reentrantlock(segment继承了reentrantlock) 当要put的时候,并不是对整个hash加锁,而是先通过hashcode定位到某一个分段中,然后对 对分段进行加锁,所以当多线程并发的时候,只要不put到一个分段,就实现了并发插入。 但是,当统计size的时候,即获取hashmap全局信息的时候,需要获取所有的分段锁才能统计。 分段锁设计目的是细化锁的粒度。 将区间按照并发级别,分成了若干个segment(默认16个),每个segment的容量默认也是16 底层是一个segment数组,每个segment类似于一个hashmap。采用了reentrantLock、volatile、final等技术实现 3.happens-before法则 程序次数法则:线程中的每个动作A都happens-before于每一个动作B 监视器锁法则:对一个监视器锁的解锁早于对用一个监视器的加锁操作 valatile法则:对volatile变量域的写入早于读入操作 线程启动法则:在一个线程里,对Thread.start的早于每个启动线程的动作 线程中断法则: 4.spring类的加载方式、实例保存在哪、aop、ioc、反射机制 单例预加载(默认) 单例懒加载 多例懒加载 beanfactory加载tomcat启动的时候,会将单例的bean实例化并放置到hashmap中,非单例的bean会从spring容器中加载。
5.设计模式 6.类加载器、双亲委派机制、热部署 bootstrap加载器、extension加载器、application加载器。 执行的动作:加载-》验证-》准备-》解析-》初始化 7.jvm内存模型、堆的分代算法、gc算法、gc过程、实例常量放在哪、方法区存什么 堆内存分代是为了提高对象的内存分配和垃圾回收的效率。 新创建的对象在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代, 常量、静态信息、类信息存放在永久代中。新生代中的对象存活时间段,需要频繁进行GC 新生代中一次GC大概可以回收70%-95%的空间。 当eden区没有足够的空间进行分配时,虚拟机将发起一次minorGC。 当进行minorGC时,对象只会存在于eden和s0区域,采用复制算法。将eden所有存活的对象复制到s1区。 s0区的对象会根据年龄值决定对象去向,达到年龄(默认15)阈值的被移动到老年代,没有达到的移动到s1区。 然后清空eden和s0,接着,s1和s0交换角色。也就是新的s0就是上次的s1,保证每次gc完成后s1是空的。 GC时,当s1区没有足够的空间时,需要依赖老年代进行分配。 fullGC发生在老年代的GC,出现fullGC一般会伴随至少一次minorGC。 当老年代内存不足或者显示调用system.gc()方法时,会触发fullGC。采用的标记-清除算法。方法区中存放的是类完整有效名、直接父类的完整有效名(接口或object除外)、类的修饰符、直接接口的一个有序列表
类的方法代码、变量名、方法名、返回值、访问权限、 8.tcp/ip 7层模型,get和post区别、长度和安全 应用层:为应用提供服务 表示层:数据格式化和数据加密 会话层:创建管理和维护连接会话 传输层:建立、管理和维护端到端的连接 网络层:ip选址及路由选择 数据链路层:访问介质管理和链路管理 物理层:物理层get请求在url中传递的参数是有长度限制的,而post没有
get请求参数通过uri传递,而post通过requestbody传递,更安全 get请求会主动被浏览器缓存、post不会。 get产生一个tcp数据包,post产生2个tcp数据包。(get请求,浏览器会把header和data一并发送过去,服务器响应200 ;post请求,浏览器先发送header,服务器响应100,然后浏览器再发送data,服务器响应200)http的报文格式:请求报文和响应报文
请求报文: 请求行:请求方法字段、rul字段以及http协议版本三个字段,如GET /index.html HTTP/1.1。 请求头部:由关键字/值组成,如: User-Agent:产生请求的浏览器类型。 Accept:客户端可识别的内容类型列表。 Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。 Content-Type: application/x-www-form-urlencoded Content-Length: 12 Connection:close 空行 请求数据: sn=123&n=asa 4部分组成。响应报文:
响应头 响应体两部分组成9.mysql的引擎区别
1)MyIASM是非事务安全的,而InnoDB是事务安全的 2)MyIASM支持全文类型索引,而InnoDB不支持全文类型索引 3)MyISAM锁粒度是表级锁,而InnoDB是行级锁 4)MyISAM相对简单,效率更高 10.redis缓存、集群部署、热备份、主从备份、主从数据库、hash映射找到指定节点 11.数据库的索引原理、b—树和hash、二叉查找树的原理 12java抽象类和接口区别。 参数 抽象类 接口 默认的方法实现 可以有默认的方法实现 完全是抽象的,没有哦任何方法实现 构造器 可以有构造器 不能有构造器 访问修饰符 可以是public、protected public默认 default等 13数据库连接池的作用 连接池是将创建好的连接保存在池中,当有请求来时,直接使用已经创建好的连接对数据进行访问。 省略了创建连接和销毁连接的过程。 好处: 1)资源复用 由于数据库连接得到重用,避免了频繁创建、释放和销毁连接引起的大量性能开销。 2)更快的系统响应时间 3)统一的连接管理,避免数据库连接泄露。 基本原理: 1.建立数据库连接池对象 2.按照事先准备的参数创建初始数量的连接 3.请求到来时,从连接池中得到一个连接,如果没有空闲的,且未达到最大数量,则创建一个新的 4.存取数据库 5.释放数据库连接、将其放入连接池中 6.释放连接池对象(服务停止、维护期间) 三个参数:最大连接数、最大空闲数、最大等待时间。
mysql事务的并发问题:
1.脏读:事务A读取了事务B更新的数据,然后事务B回滚了,那么A读到的就是脏数据。 2.不可重复读:事务A多次读取同一数据。事务B在事务A多次读取过程中,对数据做了更新并且提交。导致事务A多次读取统一数据时,结果不一致 3.幻读:系统管理员A将所有学生的成绩从具体分数改为了ABCD等级,但是系统管理员B在这个时候插入了一条具体分数的记录。当A改结束后,发现还有 一条具体分数的记录没有哦改过来,就好像发生了幻觉一样。这就是幻读 mysql事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 1.读未提交(read-uncommited) 解决 解决 解决 2.不可重复读(read-commited) 未解决 解决 解决 3.可重复读(repeatable-read) 未解决 未解决 解决 4.串行化(serializable) 未解决 未解决 未解决 mysql默认的事务隔离级别是repeatable-read 1、SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异 2、mysql中默认事务隔离级别是可重复读时并不会锁住读取到的行 3、事务隔离级别为读提交时,写数据只会锁住相应的行 4、事务隔离级别为可重复读时,如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间隙锁、行锁、下一键锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表。 5、事务隔离级别为串行化时,读写数据都会锁住整张表 6、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,鱼和熊掌不可兼得啊。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
java集合和concurrent并发包总结
1.集合包 集合包最常用的有collection和map两个接口的实现,collection用于存放单个对象,map用于存放key/value形式的键值对。 collection中最常用的分为list和set,list可以存放重复的元素,set不能存放重复元素。List的实现类有ArrayList、linkedList 、vector及stack,set实现类有hashset和treeset ArrayList基于数组实现,无容量限制,默认初始化容量大小为10 linkedlist基于双向链表机制。非线程安全。 hashset默认创建一个hashmap对象, hashmap基于数组+链表实现,put的时候根据key hash后hashcode和数组的length-1按位与的结果,判断放置在数组中的那个 位置。get的时候是根据key的hashcode确定数组的位置,再根据key的equals确定在链表处的位置。 hashtable数据结构和hashmap结构原理一致,区别在于get和put的时候加了synchronized关键字。 treemap基于红黑树实现,因此要求传入的key一定要有比较的方法。要么key对象实现comparator接口,要么传入comparator实现。 2.并发包 1.5之后增加了java.util.concurrent.*并发包,java内存模型、volatile、和AQS(AbstractQueuedSynchronizer)是并发包众多实现的基础。 java内存模型:描述了线程内存和主从间的通讯关系。 代码顺序规则:happens-before volatile变量规则: 3.AQS(AbstractQueuedSynchronizer) 抽象的队列式的同步锁。定义了一套多线程访问共享资源的同步框架集,许多同步类的实现都依赖它,比如ReentrantLock、semaphore、countDownLatch等 底层是一个state和FIFO队列。维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源别阻塞时会进入此队列) state的访问方式有三种:getState(),setState(),compareAndSetState() AQS定义了两种资源共享方式:独占(exclusive,只有一个线程能执行,如reentrantLock)方式和共享(share,多个线程可同时执行,如 semaphore、countDownLatch)方式. 不同的自定义同步器争用共享的资源方式也不同,自定义的同步器在定义时只需要实现共享资源state的获取和实现方式即可,至于线程等待队列的 维护(如获取资源入队、唤醒出队等),AQS已经在底层实现了。自定义的同步器在实现时主要实现以下几种方法 isHeldExclusively():该线程是否正在独占资源,只有用到condition才需要去实现。 boolean tryAcquire(int):独占方式获取资源 boolean tryRelease(int):独占方式释放资源 int tryAcquireShared(int):共享方式获取资源,负数表示失败,0表示成功,但没有可用资源。正数表示成功,且有可用资源 boolean tryAcquireShared(int):共享方式释放资源 ReentrantLock实现过程:state初始化为0,未锁定。A线程lock时,会调用tryAcquire()独占该锁并将state+1,此后其他线程tryAcquire时就会失败 直到A线程unLock到state=0为止。在释放锁之前,A线程也可以重复获取此锁(state会累加),就是可重入的概念。这里获取多少次就要释放多少次。 countDownLatch实现过程。N个子线程执行任务,state也初始化为N。N个线程并行执行,每个子线程执行完后countDown()一次,state就会CAS减1 所有线程执行完(state=0),会unpark()主调用线程。主就会从await()函数返回,继续后序动作。