String,Stringbuilder和Stringbuffer的区别
- String底层使用一个不可变的字符数组private final char value[];所以它内容不可变。
- StringBuffer和StringBuilder都继承了AbstractStringBuilder底层使用的是可变字符数组:char[] value;
- StringBuilder是线程不安全的,效率较高;而StringBuffer是线程安全的,效率较低。
- 通过他们的append()方法来看,StringBuffer是有同步锁,而StringBuilder没有
io流用的是什么设计模式?
- 装饰者设计模式:给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,
装饰对象持有被装饰对象的实例(各种字符流间装饰,各种字节流间装饰) - 适配器设计模式:有时候我们需要实现一个接口,但那个接口可能有很多抽象方法,我们只需要其中一个或多个方法。
这时候我们可以创建一个类(适配器)实现接口,并重写接口中所有方法(空方法,有方法体,但方法体中无内容)。
当我们需要接口中的某个方法时,只需继承类似于适配器的类 ,然后重写对应的方法即可。
将某个类的接口转换成我们期望的另一个接口表示,目的是消除由于接口不匹配所造成类的不兼容问题(字符流与字节流间互相适配)
hashMap和hashTable的区别?
- hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
- hashMap允许空键值,而hashTable不允许
- HashMap线程不安全,效率高。HashTable线程安全,效率低。
- HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast(就是最快的时间能把错误抛出而不是让程序执行。)的。
HashMap 的实现原理
- HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
- 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体
- 当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
hashTable的实现
- 和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。
Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。
Hashtable中的映射不是有序的。
ConcurrentHashMap底层怎么实现的
- 锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问
ConcurrentHashMap将整个Map分为N个segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认N为16
数据库:怎么优化的?
- 将表中字段的宽度设得尽可能小
- 尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值
- 使用联合(UNION)来代替手动创建的临时表
- 使用事务操作数据库:BEGIN; INSERT INTO salesinfo SET CustomerID=14; UPDATE inventory SET Quantity=11 WHERE item='book'; COMMIT;
(事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。) - 使用索引:选择合适的索引列,选择在where,group by,order by,on从句中出现的列作为索引项,对于离散度不大的列没有必要创建索引
- 根据业务需求分割数据库表
Redis有哪些数据类型,用Redis做过一些什么
- Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
Spring中用到了哪些设计模式
- 工厂设计模式
单例设计模式
代理设计模式
模板方法设计模式
观察者设计模式
适配器设计模式
装饰者设计模式
策略设计模式
java 中 IO 流分为几种
- 按功能来分:输入流(input)、输出流(output)。
- 按类型来分:字节流和字符流。
Collection 和 Collections 有什么区别
- java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。
- Collections则是集合类的一个工具类/帮助类
ArrayList 和 LinkedList 的区别
- 最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问
如何实现数组和 List 之间的转换
- List转换成为数组:调用ArrayList的toArray方法。
数组转换成为List:调用Arrays的asList方法。
Array 和 ArrayList 有何区别
- Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
- Array是指定大小的,而ArrayList大小是固定的。
- Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等
什么是反射
- 反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力
动态代理是什么
- 当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新类。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
深拷贝和浅拷贝区别是什么
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝(例:assign())
- 深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:JSON.parse()和JSON.stringify(),但是此方法无法复制函数类型)
如何避免 sql 注入
- PreparedStatement(简单又有效的方法)
- 使用正则表达式过滤传入的参数
- 字符串过滤
- JSP中调用函数检查是否包函非法字符
- JSP页面判断代码
throw 和 throws 的区别
- throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理。
- 而throw则是指抛出的一个具体的异常类型。
get 和 post 请求有哪些区别
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中
说一下你熟悉的设计模式
- 单例模式:
简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例 - 观察者模式:对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
- 工厂模式:简单工厂模式:一个抽象的接口,多个抽象接口的实现类,一个工厂类,用来实例化抽象的接口
- 工厂方法模式:有四个角色,抽象工厂模式,具体工厂模式,抽象产品模式,具体产品模式。不再是由一个工厂类去实例化具体的产品,而是由抽象工厂的子类去实例化产品
spring
- Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架
- Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象
- Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发
SpringMVC执行流程
前端控制器(DispatcherServlet)→ 处理器映射器(HandlerMapping),返回处理器执行链 → 处理器适配器(HandlerAdapter),返回ModelAndView → 前端控制器接受ModelAndView,并请求视图解析器解析(ViewResolver)
mybatis 中 #{}和 ${}的区别是什么
-
{}是预编译处理,${}是字符串替换;
- Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
- Mybatis在处理{}替换成变量的值;
- 使用#{}可以有效的防止SQL注入,提高系统安全性。
zookeeper 是什么
- zookeeper 是一个分布式的,开放源码的分布式应用程序协调服务,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
- 集群管理:监控节点存活状态、运行请求等。
- 主节点选举:主节点挂掉了之后可以从备用的节点开始新一轮选主,主节点选举说的就是这个选举的过程,使用 zookeeper 可以协助完成这个过程。
- 分布式锁:zookeeper 提供两种锁:独占锁、共享锁。独占锁即一次只能有一个线程使用资源,共享锁是读锁共享,读写互斥,即可以有多线线程同时读同一个资源,如果要使用写锁也只能有一个线程使用。zookeeper可以对分布式锁进行控制。
- 命名服务:在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信
息。 - zookeeper 有三种部署模式:单机部署:一台集群上运行;集群部署:多台集群运行;伪集群部署:一台集群启动多个 zookeeper 实例运行。
27、说一下 ACID
Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)
说一下 jvm 的主要组成部分?及其作用?
类加载器(ClassLoader)运行时数据区(Runtime Data Area)执行引擎(Execution Engine)本地库接口(Native Interface)
说一下 jvm 运行时数据区?
程序计数器 虚拟机栈 本地方法栈 堆 方法区
说一下堆栈的区别
- 栈内存存储的是局部变量而堆内存存储的是实体;
- 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
- 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
JVM,栈内存溢出和堆内存溢出:
- 栈:方法递归调用栈帧超过了栈的深度。堆:不断的new对象则会导致堆中的空间溢出
jdk8新特性
- Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
- 方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
- 默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
- 新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
- Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
- Date Time API − 加强对日期与时间的处理。
- Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
正向代理
一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器)然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理,正向代理总结就一句话:代理端代理的是客户端
反向代理
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求,发给内部网络上的服务器并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器反向代理总结就一句话:代理端代理的是服务端
事务的特性
- 原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响
- 一致性(Consistency)一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
- 隔离性(Isolation)隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
- 持久性(Durability)持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
jsp的内置对象
- request、response、session、application、out、pagecontext、page、config、exception
JSP中四大域对象
- page、request、session、application
数据库的乐观锁和悲观锁
- 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作
- 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性
创建线程有哪几种方式
- 继承Thread类创建线程类,并重写该类的run方法
- 定义runnable接口的实现类,并重写该接口的run()方法
- 创建Callable接口的实现类
runnable 和 callable 有什么区别
- Runnable接口中的run()方法的返回值是void
- Callable接口中的call()方法是有返回值的,是一个泛型
线程有哪些状态?
- 线程通常都有五种状态,创建(生成线程对象,并没有调用该对象的start方法)、就绪(当调用了线程对象的start方法之后)、运行(线程调度程序将处于就绪状态的线程设置为当前线程)、阻塞(sleep,wait等方法都可以导致线程阻塞)和死亡(一个线程的run方法执行结束或者调用stop方法后)
sleep() 和 wait() 有什么区别
- sleep():线程类(Thread)的静态方法,让调用线程进入睡眠状态,让出执行机会给其他线程,等到休眠时间结束后,线程进入就绪状态和其他线程一起竞争cpu的执行时间。因为sleep() 是static静态的方法,他不能改变对象的机锁
- wait():wait()是Object类的方法,当一个线程执行到wait方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问,可以通过notify,notifyAll方法来唤醒等待的线程
线程的 run()和 start()有什么区别
- 方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
- start()方法来启动一个线程,真正实现了多线程运行
- run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的
- 多线程执行时要使用start()方法而不是run()方法
java线程池核心类:ThreadPoolExecutor
- corePoolSize:核心线程数
- queueCapacity:任务队列容量(阻塞队列)
- maxPoolSize:最大线程数
- keepAliveTime:线程空闲时间
- allowCoreThreadTimeout:允许核心线程超时
- rejectedExecutionHandler:任务拒绝处理器
创建线程池有哪几种方式
- newFixedThreadPool(int nThreads)创建一个固定长度的线程池,每当提交一个任务就创建一个线程
- newCachedThreadPool()创建一个可缓存的线程池
- newSingleThreadExecutor()这是一个单线程的Executor,它创建单个工作线程来执行任务
- newScheduledThreadPool(int corePoolSize)创建了一个固定长度的线程池
线程池都有哪些状态?
线程池有5种状态:Running、ShutDown、Stop、Tidying、Terminated。
ThreadPoolExecutor执行顺序
线程池按以下行为执行任务
- 当线程数小于核心线程数时,创建线程。
- 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- 当线程数大于等于核心线程数,且任务队列已满
(若线程数小于最大线程数,创建线程,若线程数等于最大线程数,抛出异常,拒绝任务)
List、Set
- Set 接口实例存储的是无序的,不重复的数据,删除和插入效率高
- List 接口实例存储的是有序的,可以重复的元素,List检索效率高
- ArrayList是List接口的一种实现,它是使用数组来实现的。
- LinkedList是List接口的一种实现,它是使用链表来实现的。
- ArrayList 遍历和查找元素比较快。
ajax中async属性用于控制同步和异步
- true(异步请求,默认),flase(同步)
防止数据库崩溃的策略
- 主从服务器策略,主服务器异步传输数据到从服务器上
并行和并发有什么区别
- 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件
- 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务
高并发(High Concurrency)
是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。
提高系统并发能力的方式,方法论上主要有两种:
垂直扩展(Scale Up)与水平扩展(Scale Out)。前者垂直扩展可以通过提升单机硬件性能,或者提升单机架构性能,来提高并发性,但单机性能总是有极限的,互联网分布式架构设计高并发终极解决方案还是后者:水平扩展。
水平扩展:互联网分层架构中,各层次水平扩展的实践又有所不同:
(1)反向代理层可以通过“DNS轮询”的方式来进行水平扩展;
(2)站点层可以通过nginx来进行水平扩展;
(3)服务层可以通过服务连接池来进行水平扩展;
(4)数据库可以按照数据范围,或者数据哈希的方式来进行水平扩展;
并行和并发有什么区别
- 并行是在不同实体上的多个事件,并发是在同一实体上的多个事件
- 在一台处理器上“同时”处理多个任务,在多台处理器上同时处理多个任务
进程和线程的区别
- 进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。
- 进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源
- 线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位
- 同一进程中的多个线程之间可以并发执行。
守护线程(即daemon thread)
是个服务线程,准确地来说就是服务其他的线程