1.项目中SpringAOP用在什么地方,为什么这么用,切点,织入,通知,用自己的话描述一下,AOP原理,动态代理2种实现。
通知:
定义:切面也需要完成工作。在AOP术语中,切面的工作被称为通知。
工作内容:通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决何时执行这个工作。
Spring切面可应用的5种通知类型:
Before——在方法调用之前调用通知
After——在方法完成之后调用通知,无论方法执行成功与否
After-returning——在方法执行成功之后调用通知
After-throwing——在方法抛出异常后进行通知
Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
连接点:
定义:连接点是一个应用执行过程中能够插入一个切面的点。连接点可以是调用方法时、抛出异常时、甚至修改字段时、切面代码可以利用这些点插入到应用的正规流程中程序执行过程中能够应用通知的所有点。
切点:
定义:如果通知定义了“什么”和“何时”。那么切点就定义了“何处”。切点会匹配通知所要织入的一个或者多个连接点。通常使用明确的类或者方法来指定这些切点。
作用:定义通知被应用的位置(在哪些连接点)
切面:
定义:切面是通知和切点的集合,通知和切点共同定义了切面的全部功能——它是什么,在何时何处完成其功能。
引入:引入允许我们向现有的类中添加方法或属性
织入:织入是将切面应用到目标对象来创建的代理对象过程。切面在指定的连接点被织入到目标对象中,在目标对象的生命周期中有多个点可以织入。
AOP原理:面向切面编程,就是把可重用的功能提取出来,然后将这些通用功能在合适的时候织入到应用程序中,比如事务管理、权限控制、日志记录、性能统计等。
动态代理的实现:
CGLIB中的动态代理是JDKproxy的一个很好的补充,在JDK中实现代理时,要求代理类必须是继承接口的类,因为JDK最后生成的proxyclass其实就是实现了被代理类所继承的接口并且继承了java中的Proxy类,通过反射找到接口的方法,调用InvocationHandler的invoke方法实现拦截。CGLIb中最后生成的proxyclass是一个继承被代理类的class,通过重写被代理类中的非final的方法实现代理。
总结为:JDKproxy:代理类必须实现接口,不需要引来第三方库
2.Spring里面注解用过没有?autowired和resource区别
@Resource和@Autowired都是做bean的注入时使用,其实@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要导入,但是Spring支持该注解的注入。
1、共同点
两者都可以写在字段和setter方法上。两者如果都写在字段上,那么就不需要再写setter方法。
2、不同点
(1)@Autowired
@Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired;只按照byType注入。
@Autowired注解是按照类型(byType)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它的required属性为false。如果我们想使用按照名称(byName)来装配,可以结合@Qualifier注解一起使用。如下:
(2)@Resource
@Resource默认按照ByName自动注入,由J2EE提供,需要导入包javax.annotation.Resource。@Resource有两个重要的属性:name和type,而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。
所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不制定name也不制定type属性,这时将通过反射机制使用byName自动注入策略。
注:最好是将@Resource放在setter方法上,因为这样更符合面向对象的思想,通过set、get去操作属性,而不是直接去操作属性。
3.Linux命令,怎么日志文件里面找关键字
1、查看日志前n行:
cat文件名|head-n数量
demo:
cattest.log|head-n200#查看test.log前200行
2、查看日志尾n行:
cat文件名|tail-n数量
cattest.log|tail-n200#查看test.log倒数200行
3、根据关键词查看日志并返回关键词所在行:
方法一:cat路径/文件名|grep关键词
方法二:grep-i关键词路径/文件名(与方法一效果相同,不同写法而已)
单个文件可以使用vi或vim编辑器打开日志文件,使用编辑器里的查找功能。在查看模式下,符号/后面跟关键字向下查找,符号后面跟关键字向上查找,按n查找下一个,按N查找上一个。
4.怎么杀死一个进程
方法1:通过kill进程id的方式可以实现,首先需要知道进程id,例如,想要杀死firefox的进程,通过ps-ef|grepfirefox,可以查到firefox的进程id:然后通过kill3781就可以关闭进程了.补充:1.kill-9来强制终止退出,例如:kill-93781kill-9-1终止你拥有的全部进程。
方法2:killall通过程序的名字,来杀死进程例如:killallfirefox注意:该命令可以使用-9参数来强制杀死进程,killall-9firefox
方法3:pkill通过程序的名字,直接杀死所有进程例如:pkillfirefox
5.MQ,zookeeper,dubbo,redis,是否了解分布式,是否了解负载均衡?
MQ消息队列(上游--消息队列--下游)在高并发环境下,由于来不及同步处理,请求往往会发生阻塞,比如大量的insert、update之类的请求同时到达mysql,直接导致无数的行锁和表锁,从而触发toomanyconnections错误,通过消息队列,可以异步处理请求,从而缓解系统压力。
MQ的不足是:1)系统更复杂,多了一个MQ组件2)消息传递路径更长,延时会增加3)消息可靠性和重复性互为矛盾,消息不丢不重难以同时保证4)上游无法知道下游的执行结果,这一点是很致命的。调用方实时依赖执行结果的业务场景,请使用调用,而不是MQ。
什么时候使用MQ
【典型场景一:数据驱动的任务依赖】
什么是任务依赖,举个栗子,互联网公司经常在凌晨进行一些数据统计任务,这些任务之间有一定的依赖关系,比如:
1)task3需要使用task2的输出作为输入
2)task2需要使用task1的输出作为输入这样的话,tast1,task2,task3之间就有任务依赖关系,必须task1先执行,再task2执行,载task3执行。
采用MQ的优点是:
需要特别说明的是,MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据。
【典型场景二:上游不关心执行结果】
如果使用调用关系,会导致上下游逻辑+物理依赖严重
一般采用“回调网关+MQ”方案来解耦:
4)网关将返回结果通知MQ
5)请求方收到结果通知
总结
MQ是一个互联网架构中常见的解耦利器。
什么时候使用MQ?1)数据驱动的任务依赖
2)上游不关心多下游执行结果
zookeeper
1.ZooKeeper是什么?ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态,根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户2.ZooKeeper提供了什么?1)文件系统2)通知机制3.Zookeeper文件系统每个子目录项如NameService都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。有四种类型的znode:1、PERSISTENT-持久化目录节点客户端与zookeeper断开连接后,该节点依旧存在2、PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号3、EPHEMERAL-临时目录节点客户端与zookeeper断开连接后,该节点被删除4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
8.Zookeeper集群管理所谓集群管理无在乎两点:是否有机器退出和加入、选举master。对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。
9.Zookeeper分布式锁有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建/distribute_lock节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock节点就释放出锁。对于第二类,/distribute_lock已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。
10.Zookeeper队列管理两种类型的队列:1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。2、队列按照FIFO方式进行入队和出队操作。第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。
redis
Redis是一款开源的、高性能的键-值存储(key-valuestore)。它常被称作是一款数据结构服务器(datastructureserver)。
Redis的键是String类型,值可以包括字符串(strings)类型,同时它还包括哈希(hashes)、列表(lists)、集合(sets)和有序集合(sortedsets)等数据类型。对于这些数据类型,你可以执行原子操作。
为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。同时,Redis支持数据的持久化,需要经常将内存中的数据同步到磁盘来保证持久化。
Redis同样支持主从复制(master-slavereplication),并且具有非常快速的非阻塞首次同步(non-blockingfirstsynchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的事物支持、发布订阅(pub/sub)、管道(pipeline)和虚拟内存(vm)等。
Redis功能:
持久化:
redis是一个支持持久化的内存数据库,即redis需要经常将内存中的数据同步到磁盘来保证持久化,这是相对memcache来说的一个大的优势。redis支持两种持久化方式,一种是Snapshotting(快照)也是默认方式,另一种是Append-onlyfile(缩写aof)的方式。
主从复制:
主从复制允许多个slaveserver拥有和masterserver相同的数据库副本。下面是关于redis主从复制的一些特点1.master可以有多个slave。2.除了多个slave连到相同的master外,slave也可以连接其他slave形成图状结构。3.主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求。相反slave在初次同步数据时则会阻塞,不能处理client的请求。4.主从复制可以用来提高系统的可伸缩性(我们可以用多个slave专门用于client的读请求,比如sort操作可以使用slave来处理),也可以用来做简单的数据冗余。5.可以在master禁用数据持久化,只需要注释掉master配置文件中的所有save配置,然后只在slave上配置数据持久化。
事务:
redis对事务的支持目前还比较简单。redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。Multi事物开始Exec执行事务Discard放弃事物Watch监听keyUnwatch放弃所有key的监听watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。注意watch的key是对整个连接有效的,和事务一样,如果连接断开,监视和事务都会被自动清除。
发布订阅:
发布订阅(pub/sub)是一种消息通信模式。订阅者可以通过subscribe和psubscribe命令向redisserver订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redisserver发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个channel,也可以向多个channel发送消息。SubscribeUnsubscribePsubscribePunsubscribePublish
管道:
虚拟内存:
redis没有使用os提供的虚拟内存机制而是自己实现了自己的虚拟内存机制,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出内存空间用于其他需要访问的数据。
Redis应用场景:
2.排行榜应用,取TOPN操作
Redis总结:
Redis使用最佳方式是全部数据in-memory。Redis更多场景是作为Memcached的替代者来使用。当需要除key/value之外的更多数据类型支持时,使用Redis更合适。当存储的数据不能被剔除时,使用Redis更合适。(持久化)
对数据高并发读写对海量数据的高效率存储和访问对数据的高可扩展性和高可用性(分布式)
redis和memcached的区别:
1Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。2Redis支持数据的备份,即master-slave模式的数据备份。3Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
4memcache挂掉后,数据不可恢复;redis数据丢失后可以通过aof恢复在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别(我个人是这么认为的)。
负载均衡
当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有请求都会首先由它接收,调度者再根据每台服务器的负载情况将请求分配给某一台后端服务器去处理。那么在这个过程中,调度者如何合理分配任务,保证所有后端服务器都将性能充分发挥,从而保持服务器集群的整体性能最优,这就是负载均衡问题。
负载均衡算法
1、轮询法
将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
2、随机法
通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,
其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
3、源地址哈希法
源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
4、加权轮询法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
5、加权随机法
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
6、最小连接数法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。
id全局自增如何实现?
treemap
如何设计一个循环队列?
构造方法:设置队列长度
Front()从队首获取元素
Rear()从队尾获取元素
enQueue()向循环队列插入一个元素
deQueue()向循环队列删除一个元素
isEmpty()检查循环队列是否为空
isFull()检查循环队列是否已满
jdbc连接数据库的流程:
JDBC流程:第一步:加载Driver类,注册数据库驱动;第二步:通过DriverManager,使用url,用户名和密码建立连接(Connection);第三步:通过Connection,使用sql语句打开Statement对象;第四步:执行语句,将结果返回resultSet;第五步:对结果resultSet进行处理;第六步:倒叙释放资源resultSet-》preparedStatement-》connection。
抽象类和接口的使用场景:
抽象类:
1.你想要在几个关联紧密的类之间共享代码。
2.你想要继承抽象类的那些类有一些公共方法或属性抑或是有修改protected或private属性的权限。这时你也可以考虑使用抽象类。
接口:
1.用相互之间无关的类实现你的接口。举例来说,可比较的和可克隆的那些接口可以使用无关的类来实现。
2.你想指定一个特定数据类型的行为,但是不用去关心由谁来实现这一行为。
3.你想要利用多继承的优势。
springboot和spring的区别
想了解区别,其实就是SpringBoot提供了哪些特征:
1.SpringBoot可以建立独立的Spring应用程序;
2.内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了。
3.无需再像Spring那样搞一堆繁琐的xml文件的配置;
4.可以自动配置Spring;
5.提供了一些现有的功能,如量度工具,表单数据验证以及一些外部配置这样的一些第三方功能;
6.提供的POM可以简化Maven的配置;
springboot和springcloud的区别
1、Springboot是Spring的一套快速配置脚手架,可以基于springboot快速开发单个微服务;SpringCloud是一个基于SpringBoot实现的云应用开发工具;
3、springboot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,SpringCloud很大的一部分是基于Springboot来实现。
4、Springboot可以离开SpringCloud独立使用开发项目,但是SpringCloud离不开Springboot,属于依赖的关系。
springcloud包含服务注册、发现、熔断等功能。
springmvc和三层架构的区别
MVC是一种设计模式,其实现有Struts、SPringMVC等,三层架构主要有数据访问层、业务层、展现层,其展现层可以用MVC模式,数据访问层可以用Hibernate,该层所做事务直接操作数据库、业务层就是写自己业务的地方了,是针对数据层的操作。
Spring的出现,降低了三层架构的耦合,达到解耦的目的(当然Spring的作用还有很多),所以,现在就流行SSH、S2SH之类的。
归并排序思想和代码
两路归并排序算法思路:
分而治之(divide-conquer);每个递归过程涉及三个步骤第一,分解:把待排序的n个元素的序列分解成两个子序列,每个子序列包括n/2个元素.第二,治理:对每个子序列分别调用归并排序MergeSort,进行递归操作第三,合并:合并两个排好序的子序列,生成排序结果.
代码实现
aqs独占锁共享锁公平锁非公平锁
简介
AQS实现锁机制并不是通过synchronized——给对象加锁实现的,事实上它仅仅是一个工具类!它没有使用更高级的机器指令,也不靠关键字,更不依靠JDK编译时的特殊处理,仅仅作为一个普普通通的类就完成了代码块的访问控制。
AQS使用标记位+队列的方式(FIFO队列),记录获取锁、竞争锁、释放锁等一些类锁操作。但更准确的说,AQS并不关心什么是锁,对于AQS来说它只是实现了一系列的用于判断资源是否可以访问的API,并且封装了在访问资源受限时,将请求访问的线程加入队列、挂起、唤醒等操作。AQS关心的问题如下:
1.资源不可访问时,怎么处理?
3.如果有线程等不及资源了,怎么从AQS队列中退出?
至于资源能否被访问的问题,则交给子类去实现。
站在使用者的角度,AQS的功能主要分为两类:独占锁和共享锁。在它的所有子类中,要么实现了它的独占功能的API,要么实现了共享功能的API,但不会同时使用两套API,即使是ReentrantReadWriteLock,也是通过两个内部类:读锁和写锁,分别使用两套API来实现的。
当AQS的子类实现独占功能时,如ReentrantLock,资源是否可以被访问被定义为:只要AQS的state变量不为0,并且持有锁的线程不是当前线程,那么代表资源不可访问。
当AQS的子类实现共享功能时,如CountDownLatch,资源是否可以被访问被定义为:只要AQS的state变量不为0,那么代表资源不可以为访问。
ReentrantLock的加锁全部委托给内部代理类完成,ReentrantLock只是封装了统一的一套API而已,而ReentrantLock又分为公平锁和非公平锁。
公平锁:每个线程抢占锁的顺序为先后调用lock方法的顺序,并依此顺序获得锁,类似于排队吃饭;
非公平锁:每个线程抢占锁的顺序不变,谁运气好,谁就获得锁,和调用lock方法的先后顺序无关,类似后插入。
非公平锁的lock方法的处理方式:在lock的时候先直接CAS修改一次state变量(尝试获取锁),成功就返回,不成功再排队,从而达到不排队直接抢占的目的。
而对于公平锁:则是老老实实的开始就走AQS的流程排队获取锁。如果前面有人调用过其lock方法,则排在队列中前面,也就更有机会更早的获取锁,从而达到“公平”的目的。
共享锁与独占锁的对比
与AQS的独占功能一样,共享锁是否可以被获取的判断为空方法,交由子类去实现。
与AQS的独占功能不同,当锁被头节点获取后,独占功能是只有头节点获取锁,其余节点的线程继续沉睡,等待锁被释放后,才会唤醒下一个节点的线程,而共享功能是只要头节点获取锁成功,就在唤醒自身节点对应的线程的同时,继续唤醒AQS队列中的下一个节点的线程,每个节点在唤醒自身的同时还会唤醒下一个节点对应的线程,以实现共享状态的“向后传播”,从而实现共享功能。
synchronized可重入怎么实现
可重入:
若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(reentrant或re-entrant)的。
即当该子程序正在运行时,执行线程可以再次进入并执行它,仍然获得符合设计时预期的结果。与多线程并发执行的线程安全不同,可重入强调对单个线程执行时重新进入同一个子程序仍然是安全的。
我们回来看synchronized,synchronized拥有强制原子性的内部锁机制,是一个可重入锁。因此,在一个线程使用synchronized方法时调用该对象另一个synchronized方法,即一个线程得到一个对象锁后再次请求该对象锁,是永远可以拿到锁的。
在Java内部,同一个线程调用自己类中其他synchronized方法/块时不会阻碍该线程的执行,同一个线程对同一个对象锁是可重入的,同一个线程可以获取同一把锁多次,也就是可以多次重入。原因是Java中线程获得对象锁的操作是以线程为单位的,而不是以调用为单位的。
之前谈到过,每个锁关联一个线程持有者和一个计数器。当计数器为0时表示该锁没有被任何线程持有,那么任何线程都都可能获得该锁而调用相应方法。当一个线程请求成功后,JVM会记下持有锁的线程,并将计数器计为1。此时其他线程请求该锁,则必须等待。而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增。当线程退出一个synchronized方法/块时,计数器会递减,如果计数器为0则释放该锁。
手写一个线程安全的生产者和消费者
importjava.util.*;
publicclassconsumer{
/***@paramargs*///消费者privateList
synchronized(queue){if(queue.size()==0){queue.wait();queue.notifyAll();}intdata=queue.remove(0);}Thread.sleep(1000);}}catch(InterruptedExceptione){e.printStackTrace();}}publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstub}
}
//生产者classProducerimplementsRunnable{privateList
publicProducer(List
@Overridepublicvoidrun(){try{while(true){
if(Thread.currentThread().isInterrupted())break;Randomr=newRandom();longdata=r.nextInt(100);synchronized(queue){if(queue.size()>=length){queue.notifyAll();queue.wait();}elsequeue.add(data);}Thread.sleep(1000);}}catch(InterruptedExceptione){e.printStackTrace();}
java中的io
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader
字符输出流:Writer
linux如何查找某个目标字符串在文件的哪一行
grep-n"xxx"file其中xxx为要查找的字符串,file为文件名
tcp与udp的应用场景
注重通信的实时性与可靠性应该选用tcp如文件传输、重要状态的更新,邮件、浏览器等
注重通信数据的完整性以及速度时应该选用udp如视频传输、实时通信等。
spring中bean的生命周期:
apache和tomcat的区别
1.apache是web服务器,tomcat是应用(java)服务器,它只是一个servlet(jsp也翻译成servlet)容器,可以认为是apache的扩展。
2..apache和tomcat都可以做为独立的web服务器来运行。但是apache不能解释java程序(jsp,serverlet)
3.Apache是普通服务器,本身只支持html即普通网页。不过可以通过插件支持PHP,还可以与Tomcat连通(单向Apache连接Tomcat,就是说通过Apache可以访问Tomcat资源。反之不然)
4.两者都是一种容器,只不过发布的东西不同。apache是html容器,功能像IIS一样,tomcat是jsp/servlet容器,用于发布JSP及JAVA的,类似的有IBM的webshere、EBA的Weblogic,sun的JRun等
5.apache和tomcat是独立的,在同一台服务器上可以集成。
数据库查询变慢了怎么办?
1.根据查询条件,建立索引;2.优化查询程序;3.提高网速;4.扩大服务器的内存;5.若可能增加服务器CPU个数;
6.分库分表数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。
object类的结构
内存泄露的例子
内存泄漏:申请内存后,无法释放已申请的空间,无用对象持续占有内存得不到及时释放。
1.静态集合类:静态集合类生命周期和应用程序一样长。
2.监听器:在释放的时候没有删除监听器
3.物理连接:数据库连接和网络连接,除非显式关闭,否则不会自动被gc回收
4.内部类
5.单例模式:单例对象持有一个外部对象的引用,那么这个外部对象就不会被回收。
groupby子句使用注意事项
当查询中存在groupby子句时,select列表(或是having子句)中只能存在分组函数,或是出现在groupby子句中的字段。分组函数:max,min,sum,avg,count。