Java 面试题 百度/参考的答案

  • "a=b"和"a.equals(b)"有什么区别?
    若是 a 和 b 都是对象,则 a==b 是比较两个对象的引用,只有当 a 和 b 指向的是堆中的同一个对象才会返回 true,而 a.equals(b) 是进行逻辑比较,当内容相同时,返回true,因此一般须要重写该方法来提供逻辑一致性的比较。
        例如,String 类重写 equals() 方法,因此能够用于两个不一样对象,可是包含的字母相同的比较。
  • 说明ArrayList,Vector,LinkedList的存储性能和特性?
    ArrayList 和Vector他们底层的实现都是同样的,都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增长和插入元素,它们都容许直接按序号索引元素,可是插入元素要涉及数组元素移动等内存操做,因此索引数据快而插入数据慢。
          Vector中的方法因为添加了synchronized修饰,所以Vector是线程安全的容器,但性能上较ArrayList差,所以已是Java中的遗留容器。
          LinkedList使用双向链表实现存储(将内存中零散的内存单元经过附加的引用关联起来,造成一个能够按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据须要进行前向或后向遍历,可是插入数据时只须要记录本项的先后项便可,因此插入速度较快。            
          Vector属于遗留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),已经不推荐使用,可是因为ArrayList和LinkedListed都是非线程安全的,若是遇到多个线程操做同一个容器的场景,则能够经过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另外一个类的构造器中建立新的对象来加强实现)。
  • Overload和Override的区别,Overload的是否能够修改返回值?
    Overload是重载的意思,
    
    Override是覆盖的意思,也就是重写。
    
    重载Overload表示同一个类中能够有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不一样)。
    
    重写Override表示子类中的方法能够与父类中的某个方法的名称和参数彻底相同,经过子类建立的实例对象调用这个方法时,将调用子类中的定义方法,这至关于把父类中定义的那个彻底相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。
    
    子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,由于子类能够解决父类的一些问题,不能比父类有更多的问题。
    
    子类方法的访问权限只能比父类的更大,不能更小。
    
    若是父类的方法是private类型,那么,子类则不存在覆盖的限制,至关于子类中增长了一个全新的方法。
    重载overload的特色就是与返回值无关,只看参数列表,因此重载的方法是能够改变返回值类型的。因此,若是两个方法的参数列表彻底同样,是不能经过让他们的返回值类型不一样来实现重载的。咱们能够用反证法来讲明这个问题,由于咱们有时候调用一个方法时也能够不定义返回结果变量,即不要关心其返回结果,例如,咱们调用map.remove(key)方法时,虽然remove方法有返回值,可是咱们一般都不会定义接收返回结果的变量,这时候假设该类中有两个名称和参数列表彻底相同的方法,仅仅是返回类型不一样,java就没法肯定编程者倒底是想调用哪一个方法了,由于它没法经过返回结果类型来判断。
  • sleep和wait的区别?
    对于sleep()方法,咱们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
    sleep()方法致使了程序暂停执行指定的时间,让出cpu该其余线程,可是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
    在调用sleep()方法的过程当中,线程不会释放对象锁。
    而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
    获取对象锁进入运行状态。
  • java中WeakReference与SoftReference的区别?
    转载自:http://blog.csdn.net/zhandoushi1982/article/details/8745027
    
    在Java 1.2中就引入了java.lang.ref这个包,WeakReference就属于这个包。WeakReference是干吗的呢,一言弊之,它是和Java中的垃圾回收相关的。若是一个对象只有WeakReference引用它,那么这个对象就可能被垃圾回收器回收。
    
            在什么场合下应用WeakReference呢?
    
    (1) 有时咱们会碰到一些不能继承的类,如final class,没法继承它。假如咱们要使用一个Widget类,由于某种缘故没法继承该类来加入某个功能。可是,咱们必须将每一个Widget对象和某个序列号关联,而Widget自己没有serial number这个属性,这时该怎么作呢?
    
            你也许已经想到,用HashMap:serialNumberMap.put(widget, widgetSerialNumber);这看起来工做的很好。可是有个问题:当咱们再也不须要某个Widget的serial number信息,此时应该从HashMap中将这个Entry移除,若是咱们忘记了怎么办?由于HashMap中持有对这个对象的引用,这个对象永远不会被垃圾回收器回收,这就形成了内存泄漏!这意味着咱们须要像没有垃圾回收功能的语言同样,手动管理内存!可是咱们用的是Java。
    
    (2)另外一个很常见的问题是缓存。若是使用强引用,那么咱们缓存的对象就会一直滞留在内存中,不会被回收,除非咱们手动的将其从缓存中移除。此外,这还须要咱们决定什么时候从缓存中移除对象,又一个手动管理内存的问题!此时,WeakReference就显示出它的价值了。如何建立一个WeakReference呢?
      要注意的是,当调用weakReference.get()可能返回null(意味着指向的对象已经被回收)。其实,对于Widget serial number这个问题,最简单的方法是使用WeakHashMap,它的使用和普通的HashMap彻底同样,不一样点在于,WeakHashMap的key被实现为一种WeakReference(注意,是key而不是value),当key对象被回收后,WeakHashMap会自动将对应的entry移除。更精确的说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收。
    (3)Java中有四种类型的引用,按照强弱关系依次为:Strong Reference>Soft Reference>WeakReference> Phantom Reference。其中,咱们日常用的就是Strong Reference,而Phantom Reference不多用到,那么什么是Soft Reference呢?
    
            Soft Reference和weak reference的区别是:一旦gc发现对象是weak reference可达就会把它放到ReferenceQueue中,而后等下次gc时回收它;当对象是Soft reference可达时,gc可能会向操做系统申请更多内存,而不是直接回收它,当实在没辙了才回收它。像cache系统,最适合用Soft reference。让gc来替咱们决定何时回收对象以及回收哪些对象。差异样例以下:WeakReference的模型
    
     A obj = new A();      
    WeakReference wr = new WeakReference(obj);  
    obj = null;  
    //等待一段时间,obj对象就会被垃圾回收 
    ...   
    if (wr.get()==null) 
    {  
         System.out.println("obj 已经被清除了 ");  
    } else {   
         System.out.println("obj 还没有被清除,其信息是 "+obj.toString()); 
    }
  • SimpleDataFormat是线程非安全的,如何更好的使用而避免风险?
    详细转载https://blog.csdn.net/leonzhang1027/article/details/79480138
    咱们经过看JDK源码来看看为何SimpleDateFormat和DateFormat类不是线程安全的真正缘由:
      SimpleDateFormat继承了DateFormat,在DateFormat中定义了一个protected属性的 Calendar类的对象:calendar。只是由于Calendar累的概念复杂,牵扯到时区与本地化等等,Jdk的实现中使用了成员变量来传递参数,这就形成在多线程的时候会出现错误。
    calendar.setTime(date)这条语句改变了calendar,稍后,calendar还会用到(在subFormat方法里),而这就是引起问题的根源。想象一下,在一个多线程环境下,有两个线程持有了同一个SimpleDateFormat的实例,分别调用format方法:
      线程1调用format方法,改变了calendar这个字段。
      中断来了。
      线程2开始执行,它也改变了calendar。
      又中断了。
      线程1回来了,此时,calendar已然不是它所设的值,而是走上了线程2设计的道路。若是多个线程同时争抢calendar对象,则会出现各类问题,时间不对,线程挂死等等。
      分析一下format的实现,咱们不难发现,用到成员变量calendar,惟一的好处,就是在调用subFormat时,少了一个参数,却带来了这许多的问题。其实,只要在这里用一个局部变量,一路传递下去,全部问题都将迎刃而解。
      这个问题背后隐藏着一个更为重要的问题--无状态:无状态方法的好处之一,就是它在各类环境下,均可以安全的调用。衡量一个方法是不是有状态的,就看它是否改动了其它的东西,好比全局变量,好比实例的字段。format方法在运行过程当中改动了SimpleDateFormat的calendar字段,因此,它是有状态的。
    
      这也同时提醒咱们在开发和设计系统的时候注意下一下三点:
    
      1.本身写公用类的时候,要对多线程调用状况下的后果在注释里进行明确说明
    
      2.对线程环境下,对每个共享的可变变量都要注意其线程安全性
    
      3.咱们的类和方法在作设计的时候,要尽可能设计成无状态的
     三.解决办法
    
      1.须要的时候建立新实例:
          说明:在须要用到SimpleDateFormat 的地方新建一个实例,无论何时,将有线程安全问题的对象由共享变为局部私有都能避免多线程问题,不过也加剧了建立对象的负担。在通常状况下,这样其实对性能影响比不是很明显的。
         2.使用同步:同步SimpleDateFormat对象
        说明:当线程较多时,当一个线程调用该方法时,其余想要调用此方法的线程就要block,多线程并发量大的时候会对性能有必定的影响
        3.使用ThreadLocal:
        说明:使用ThreadLocal, 也是将共享变量变为独享,线程独享确定能比方法独享在并发环境中能减小很多建立对象的开销。若是对性能要求比较高的状况下,通常推荐使用这种方法。
     4.抛弃JDK,使用其余类库中的时间格式化类:
      1.使用Apache commons 里的FastDateFormat,宣称是既快又线程安全的SimpleDateFormat, 惋惜它只能对日期进行format, 不能对日期串进行解析。
      2.使用Joda-Time类库来处理时间相关问题
      作一个简单的压力测试,方法一最慢,方法三最快,可是就算是最慢的方法一性能也不差,通常系统方法一和方法二就能够知足,因此说在这个点很难成为你系统的瓶颈所在。从简单的角度来讲,建议使用方法一或者方法二,若是在必要的时候,追求那么一点性能提高的话,能够考虑用方法三,用ThreadLocal作缓存。
    
      Joda-Time类库对时间处理方式比较完美,建议使用。
  • 什么事线程局部变量?
    早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类能够很简洁地编写出优美的多线程程序。
      ThreadLocal,顾名思义,它不是一个线程,而是线程的一个本地化对象。当工做于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每一个使用该变量的线程分配一个独立的变量副本。因此每个线程均可以独立地改变本身的副本,而不会影响其余线程所对应的副本。从线程的角度看,这个变量就像是线程的本地变量,这也是类名中“Local”所要表达的意思。
      线程局部变量并非Java的新发明,不少语言(如IBM XL、FORTRAN)在语法层面就提供线程局部变量。在Java中没有提供语言级支持,而以一种变通的方法,经过ThreadLocal的类提供支持。因此,在Java中编写线程局部变量的代码相对来讲要笨拙一些,这也是为何线程局部变量没有在Java开发者中获得很好普及的缘由。
    
      学习JDK中的类,首先看下JDK API对此类的描述,描述以下:
    
      该类提供了线程局部 (thread-local) 变量。这些变量不一样于它们的普通对应物,由于访问某个变量(经过其 get 或 set 方法)的每一个线程都有本身的局部变量,它独立于变量的初始化副本。ThreadLocal 实例一般是类中的 private static 字段,它们但愿将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
      API表达了下面几种观点:
      1、ThreadLocal不是线程,是线程的一个变量,你能够先简单理解为线程类的属性变量。
    
      2、ThreadLocal在类中一般定义为静态变量。
    
      3、每一个线程有本身的一个ThreadLocal,它是变量的一个“拷贝”,修改它不影响其余线程。
    
      既然定义为类变量,为什么为每一个线程维护一个副本(姑且称为“拷贝”容易理解),让每一个线程独立访问?多线程编程的经验告诉咱们,对于线程共享资源(你能够理解为属性),资源是否被全部线程共享,也就是说这个资源被一个线程修改是否影响另外一个线程的运行,若是影响咱们须要使用synchronized同步,让线程顺序访问。
    
      ThreadLocal适用于资源共享但不须要维护状态的状况,也就是一个线程对资源的修改,不影响另外一个线程的运行;这种设计是‘空间换时间’,synchronized顺序执行是‘时间换取空间’。
  • JRE,JDK,JVM,JIT之间有什么不一样?
    java虚拟机(JVM)
        使用java编程语言的主要优点就是平台的独立性。你曾经想知道过java怎么实现平台的独立性吗?对,就是虚拟机,它抽象化了硬件设备,开发者和他们的程序的得以操做系统。虚拟机的职责就是处理和操做系统的交流。java不一样的接口规范对任何平台都有良好的支持,由于jvm很好的实现了每一个平台的规范。jvm能够理解伪代码字节码,在用户和操做系统之间创建了一层枢纽。
     
    java运行时环境(JRE)
        java运行时环境是JVM的一个超集。JVM对于一个平台或者操做系统是明确的,而JRE确实一个通常的概念,他表明了完整的运行时环境。咱们在jre文件夹中看到的全部的jar文件和可执行文件都会变成运行时的一部分。事实上,运行时JRE变成了JVM。因此对于通常状况时候使用JRE,对于明确的操做系统来讲使用JVM。当你下载了JRE的时候,也就自动下载了JVM。
     
    java开发工具箱(JDK)
        java开发工具箱指的是编写一个java应用所须要的全部jar文件和可执行文件。事实上,JRE是JDK的一部分。若是你下载了JDK,你会看到一个名叫JRE的文件夹在里面。JDK中要被牢记的jar文件就是tools.jar,它包含了用于执行java文档的类还有用于类签名的jar包。
     
    即时编译器(JIT)
        即时编译器是种特殊的编译器,它经过有效的把字节码变成机器码来提升JVM的效率。JIT这种功效很特殊,由于他把检测到的类似的字节码编译成单一运行的机器码,从而节省了CPU的使用。这和其余的字节码编译器不一样,由于他是运行时(第一类执行的编译?)the firs of its kind to perform the compilation(从字节码到机器码)而不是在程序运行以前。正是由于这些,动态编译这个词汇才和JIT有那么紧密的关系。
    转载:https://www.cnblogs.com/xiaozhijing/p/7919455.html
  • 谈谈对设计模式的认识与理解,简单介绍一下你所掌握的设计模式?
    1,设计模式是为了解决现实的问题,是对某种问题的解决方案。
    2,“对变化点的封装”出现的不少,我认为,这点是程序能够进行扩展的编程方法。这个应该是开闭原则要达到的目标。
    3,编程原则是“道”,设计模式是“术”,使用模式的时候,必定要始终贯彻原则。
    4,设计模式是基于面向对象的语言,尤为是继承,而且用多态的方式来保证程序增长功能,不用修改原代码。(面向过程不知道能不能实现)
    5,代码的可扩展性,我以为主要就是开闭原则所带来的效果,
    6,设计模式虽说是模式,可是代码的实现方法其实很灵活,他对应的应该是一种问题,或者说是如何封装变化点,具体的封装方法实现起来比较灵活。
    7,程序常常会有不少须要改变的地方,到底需不须要封装变化点,根本的原则在什么地方?
    下面说说我对几个模式的认识,
    1,简单工厂模式,解决的是客户端经过大量的判断来选择相应的对象,须要进行封装的问题。特色是判断的条件须要统一,好比字符串,或者一个特定的值。使用的结果就是判断由工厂方法来作。而且能够经过继承和多态,使得相同的语句返回一系列拥有共同父类的对象。
    2,策略模式,解决的是客户端选择方法的封装方法(与之相比的是简单工厂模式封装的是对象),其实把简单工厂模式稍做修改,就是策略模式了。能够认为是用简单工厂模式返回了一系列有共同父类或者同一接口的对象,而后调用对象的接口或者虚方法。这样客户端代码只是经过工厂生成了一个对象,而后调用对象的方法,并经过多态来实现不一样的程序功能。
    3,装饰模式,解决的问题是,如今有一个对象,咱们想给他增长方法或者属性,怎么去作,而且能够随意修改增长方法和属性的顺序。其实我首先想到的是c#的扩展方法。感受和扩展方法的目的差很少。
    4,工厂模式,,,正在看。怎么看怎么以为好像在作无用功。。。。。不知道他是干吗的。
    
    结合我如今的工做,我最近在作网页处理程序,ashx。
    我就在想这种处理程序,处理网络请求,我如今用的基本都是面向过程的,就是判断传过来什么方法,执行什么操做。用switch来跳转。
    如今我有几个疑问:
    1,这种很符合策略模式,我如今要不要使用策略模式?为何?
    2,是否是永远都要等到问题出现了,才去引用设计模式?
    3,当问题出现的时候,可能须要修改的地方就已经不少了,这时候怎么办?
  • 有三个页面,a.jsp,b.jsp,c.jsp,流程是a.jsp->b.jsp->c.jsp,如今a.jsp提交了数据,须要在c.jsp访问,用最简单最安全的方法怎么作?hibernate或ibatis,任选一种,描述下工做原理?
    用隐藏表单域,即在b.jsp页面中用n个hidden把上一页面提交过来的信息保存下来,而后和当前一块儿提交,再到c.jsp里面获取 
    说明:尽可能不要用session和少用session
  • 简述Spring事务的传播行为和隔离级别?
    详细转载:https://blog.csdn.net/yujin753/article/details/42242297
    传播行为:
        Required:默认的事务传播行为,表示必须有逻辑事务,不然新建一个事务,使用PROPAGATION_REQUIRED指定,表示若是当前存在一个逻辑事务,则加入该逻辑事务,不然将新建一个逻辑事务
    RequiresNew:建立新的逻辑事务,使用            
         PROPAGATION_REQUIRES_NEW指定,表示每次都建立新的逻辑事务(物理事务也是不一样的)所以外部事务能够不受内部事务回滚状态的影响独立提交或者回滚。
         Supports:支持当前事务,使用PROPAGATION_SUPPORTS指定,指若是当前存在逻辑事务,就加入到该逻辑事务,若是当前没有逻辑事务,就以非事务方式执行。
         NotSupported:不支持事务,若是当前存在事务则暂停该事务,使用PROPAGATION_NOT_SUPPORTED指定,即以非事务方式执行,若是当前存在逻辑事务,就把当前事务暂停,以非事务方式执行。
    
        Mandatory:使用PROPAGATION_MANDATORY指定,若是当前有事务,使用当前事务执行,若是当前没有事务,则抛出异常(IllegalTransactionStateException)。
    
        Never:不支持事务,若是当前存在是事务则抛出IllegalTransactionStateException异常,使用PROPAGATION_NEVER指定。
    
       Nested:嵌套事务支持,使用PROPAGATION_NESTED指定,若是当前存在事务,则在嵌套事务内执行,若是当前不存在事务,则建立一个新的事务,嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将致使嵌套事务回滚。
    
    Nested和RequiresNew的区别: 
    RequiresNew每次都建立新的独立的物理事务,而Nested只有一个物理事务;
    Nested嵌套事务回滚或提交不会致使外部事务回滚或提交,但外部事务回滚将致使嵌套事务回滚,而 RequiresNew因为都是全新的事务,因此之间是无关联的;
    Nested使用JDBC 3的保存点实现,即若是使用低版本驱动将致使不支持嵌套事务。
        实际应用中通常使用默认的事务传播行为,偶尔会用到RequiresNew和Nested方式。  
    
    隔离级别:
         1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
          另外四个与JDBC的隔离级别相对应
         2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务能够看到这个事务未提交的数据。
          这种隔离级别会产生脏读,不可重复读和幻像读。
         3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另一个事务读取。另一个事务不能读取该事务未提交的数据
         4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别能够防止脏读,不可重复读。可是可能出现幻像读。
          它除了保证一个事务不能读取另外一个事务未提交的数据外,还保证了避免下面的状况产生(不可重复读)。
         5. ISOLATION_SERIALIZABLE 这是花费最高代价可是最可靠的事务隔离级别。事务被处理为顺序执行。
          除了防止脏读,不可重复读外,还避免了幻像读。
  • memcached是怎么工做的?你好知道哪些缓存?
    详细转载:https://blog.csdn.net/tiedao123456789/article/details/9222475
    Memcached的工做原理
    
    Memcached处理的原子是每个(key,value)对(如下简称kv对),key会经过一个hash算法转化成hash-key,便于查找、对比以及作到尽量的散列。同时,memcached用的是一个二级散列,经过一张大hash表来维护。
    
    Memcached有两个核心组件组成:服务器端(server)和客户端(client),在一个memcached的查询中,client先经过计算key的hash值来肯定kv对所处在的server位置。当server肯定后,客户端就会发送一个查询请求给对应的server,让它来查找确切的数据。由于这之间没有交互以及多播协议,因此memcached交互带给网络的影响是最小化的。
    
    举例说明:考虑如下这个场景,有三个client分别是c1,c2,c3,还有三个ms分别是s1,s2,s3:
    
    设置kv对 
    c1想设置key=”com”,value=”iQiyi”
    c1拿到server列表,并对key作hash转化,根据hash值肯定kv对所存的server位置
    s2被选中了
    c1链接上s2,s2收到请求,把(key=”com”,value=”iQiyi”)存了起来
    
    获取kv对
    c3想获得key=”com”的value
    c3用相同的hash算法算出hash值,并肯定key=”aa”的值存在s2上
    c3链接上s2,并从s2那边获得value=”iQiyi”
    其余任何从c1,c2,c3的想获得key=”com”的值的请求都会发向s2
  • 数据库中的锁包括什么?解释一下什么事欢乐锁?什么事悲观锁?
    数据中的锁分为两类:悲观锁和乐观锁,锁还有表级锁、行级锁 
    表级锁例如: 
    SELECT * FROM table WITH (HOLDLOCK) 其余事务能够读取表,但不能更新删除 
    SELECT * FROM table WITH (TABLOCKX) 其余事务不能读取表,更新和删除 
    行级锁例如: 
    select * from table_name where id = 1 for update; 
    悲观锁(Pressimistic Locking) 
    对数据被外界(包括本系统当前的其余事务,以及来自 
    外部系统的事务处理)修改持保守态度,所以,在整个数据处理过程当中,将数据处于锁定状态。悲观锁的实现,每每依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,不然,即便在本系统中实现了加锁机制,也没法保证外部系 
    统不会修改数据)。例如: 
    select * from table_name where id = ‘xxx’ for update; 
    这样查询出来的这一行数据就被锁定了,在这个update事务提交以前其余外界是不能修改这条数据的,可是这种处理方式效率比较低,通常不推荐使用。 
    乐观锁(Optimistic Locking) 
    相对悲观锁而言,乐观锁机制采起了更加宽松的加锁机制。悲观锁大多数状况下依靠数据库的锁机制实现,以保证操做最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销每每没法承受。如一个金融系统,当某个操做员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户账户余额),若是采用悲观锁机制,也就意味着整个操做过程当中(从操做员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操做员中途去煮咖啡的时间),数据库记录始终处于加锁状态,能够想见,若是面对几百上千个并发,这样的状况将致使怎样的后果。 
    乐观锁机制在必定程度上解决了这个问题。乐观锁,大可能是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增长一个版本标识,在基于数据库表的版本解决方案中,通常是经过为数据库表增长一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,以后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,若是提交的数据版本号大于数据库表当前版本号,则予以更新,不然认为是过时数据。 
    举个乐观锁的例子(数据库version默认为0): 
    不如如今一件衣服就剩一个库存了,可是有两个用户同时下单,若是这时候不加以控制很容易出现库存卖超的状况,这时候咱们能够这样操做: 
    第一个用户将这件衣服读出(version=0),并将库存-1, 
    第二个用户也将这件衣服读出(version=0),并将库存-1, 
    第一个个用户完成操做,将数据库版本version+1,执行更新库存时因为提交的数据版本大于数据库记录的版本,数据被更新,数据库中的version被更新为2。 
    update goods set store=store-1,version=version+1 where id=xx and version=orginal_version 
    第二个用户也完成了操做,也将版本version+1,执行更新库存时发现执行版本和数据库记录的版本相同,不符合提交版本必须大于数据库记录版本的乐观锁策略,因此第二个用户的下单请求被驳回,咱们能够经过人性化处理异常给用户提示该商品已售罄等。 
    乐观锁机制避免了长事务中的数据库加锁开销(两个用户操做过程当中,都没有对数据库数据加锁),大大提高了大并发量下的系统总体性能表现。 
    悲观锁:交给数据库来处理的,由事务(分隐私和显式事务,平时单条SQL语句就是一个隐式事务)+锁 那控制的,其中事务至关于锁的做用域,根据事务的提交失败或回滚来释放掉显式事务中开启的锁。(事前处理) 
    乐观锁:是认为版本号来控制的,这种机制并发性和性能更好(过后处理)
  • mysql或Oracle查询优化,要应该注意哪些事项?
详细转载:https://blog.csdn.net/bravekingzhang/article/details/19081467

1. 为查询缓存优化你的查询
2. EXPLAIN 你的 SELECT 查询
3. 当只要一行数据时使用 LIMIT 1
4. 为搜索字段建索引
5. 在Join表的时候使用至关类型的例,并将其索引
6. 千万不要 ORDER BY RAND()
7. 避免 SELECT *
8. 永远为每张表设置一个ID
9. 使用 ENUM 而不是 VARCHAR
10. 从 PROCEDURE ANALYSE() 取得建议
11. 尽量的使用 NOT NULL
12. Prepared Statements
13. 无缓冲的查询
14. 把IP地址存成 UNSIGNED INT
15. 固定长度的表会更快
16. 垂直分割
17. 拆分大的 DELETE 或 INSERT 语句
18. 越小的列会越快
19. 选择正确的存储引擎
20. 使用一个对象关系映射器(Object Relational Mapper)
21. 当心“永久连接”
  • 分布式session共享怎么设计?
    1、Session Replication 方式管理 (即session复制)
                简介:将一台机器上的Session数据广播复制到集群中其他机器上
                使用场景:机器较少,网络流量较小
                优势:实现简单、配置较少、当网络中有机器Down掉时不影响用户访问
                缺点:广播式复制到其他机器有必定廷时,带来必定网络开销
        2、Session Sticky 方式管理
                简介:即粘性Session、当用户访问集群中某台机器后,强制指定后续全部请求均落到此机器上
               使用场景:机器数适中、对稳定性要求不是很是苛刻
               优势:实现简单、配置方便、没有额外网络开销
                缺点:网络中有机器Down掉时、用户Session会丢失、容易形成单点故障
        3、缓存集中式管理
               简介:将Session存入分布式缓存集群中的某台机器上,当用户访问不一样节点时先从缓存中拿Session信息
               使用场景:集群中机器数多、网络环境复杂
               优势:可靠性好
               缺点:实现复杂、稳定性依赖于缓存的稳定性、Session信息放入缓存时要有合理的策略写入

     

  • java的类加载机制的原理?
    类加载是一个将类合并到正在运行着的JVM进程中的过程。首先要加载一个类,咱们必须先得将类文件加载进来并链接,而且要加上大量的验证,随后会生成一个表明着这个类的class对象,而后就能够经过它去建立新的实例了。
        这就是我所理解的Java的类加载机制。
        通过加载和链接后出来的class对象,说明这个类已经被加载到了JVM中,此后就不会再加载了。

     

  • SQL注入攻击和XSS攻击
  • MVC框架和ORM框架
  • EJB和spring
  • jboss和weblogic
  • DNS服务,CDN服务,
  • CGI
  • spring mvc中datasource配置
  • String StringBuilder StringBuffer有什么不一样?
相关文章
相关标签/搜索