一、session共享

客户端cookie方式、利用redis、利用数据库、使用软负载nginx和硬负载F5做会话保持;


二、session共享原理

创建一个顶级filter,重新包装request和response,重新实现getSession或接管HttpSession;


三、spring session原理

首先集成一个SessionRepositoryFilter是一个优先级最高的javax.servlet.Filter,它使用了一个SessionRepositoryRequestWrapper类接管了Http Session的创建和管理工作。然后通过SessionRepositoryRequestWrapper与SessionRepositoryResponseWrapper,对原有的request和response进行一层装饰,通过SessionRepository去操纵session;


四、HashMap、ArrayList、LinkedList原理

ArrayList:数组;寻址容易,插入和删除困难;

LinkedList:链表;寻址困难,插入和删除容易。

HashMap:哈希表,链表+数组;寻址容易,插入删除也容易。

1)Entry,属性有 key , value, next;存储的就是Entry[];

2)hash = key.hashCode();index = hash % Entry[].length;

3)位置相同的,通过Entry.next进行存储;

4)null存储在第一个位置;

5)当HashMap中的元素个数超过数组大小(16)*loadFactor(0.75)时,就会进行数组扩容;也就是当大于16*0.75=12就会,扩容重新计算,扩大一倍 2*16=32;所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。


五、集群同步锁

1. 用数据库,在数据库建一张表,需要锁的节点都可以尝试用 select * from Lock where id=xx for update. 这个时候只有一个节点能拿到结果,其它的都会等待,就能实现一个简单的悲观锁。

2. 用 Zookeeper 来做分布式锁。

3. 通过redis实现同步锁。

4. 自己实现,搞个节点来做这个事情,所有要获取锁的都走 RPC 调用来请求锁,用完以后记得释放,不然其他的节点就会挂那里。自己实现很危险的。


六、集群重复处理问题

1)客户端点击后,应该禁用按钮,避免重复发送;

2)token;在集群同步锁的作用下,请求是需要排队的;这个时候我们只需要通过token就能够解决这个问题;

3)请求加入随机数和时间戳,通过url重复验证也可以避免;只要做好锁和排队机制,这种方法也是可以的;


七、IO(BIO)、NIO、AIO

Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理;


---------------------------------------------------------


1)servlet 生命周期

Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。


2)spring ioc 生命周期

总结:

spring生命周期的过程为:

BeanFactoyPostProcessor实例化;先执行Bean的构造函数;通过XML配置文件注入相应的属性值;执行InitializingBean接口提供的afterPropertiesSet()方法;执行配置文件提供的init-method方法;使用已经初始化完毕的Bean对象;执行DisposableBean接口提供的destroy方法;执行配置文件提供的destroy-method方法


Spring的生命周期.

1.容器启动,实例化所有实现了BeanFactoyPostProcessor接口的类。他会在任何普通Bean实例化之前加载.

2.实例化剩下的Bean,对这些Bean进行依赖注入。

3.如果Bean有实现BeanNameAware的接口那么对这些Bean进行调用setBeanFactory()

4.如果Bean有实现BeanFactoryAware接口的那么对这些Bean进行调用

5.如果Bean有实现ApplicationContextAware接口的那么对这些Bean进行调用

6.如果配置有实现BeanPostProcessor的Bean,那么调用它的postProcessBeforeInitialization方法

7.如果Bean有实现InitializingBean接口的afterPropertiesSet(),那么对这些Bean进行调用

如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法

8.如果Bean配置有init属性(Bean定义文件中定义init-method),那么调用它属性中设置的方法

9.如果配置有实现BeanPostProcessor的Bean,那么调用它的postProcessAfterInitialization的ProcessaAfterInitialization()方法

10.   Bean正常是使用

11.   调用DisposableBean接口的destory方法

在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法

12.   调用Bean定义的destory方法(Bean定义文件中定义destroy-method)

在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称


3)线程实现方法

有三种:

(1)继承Thread类,重写run函数

class xx extends Thread{  

public void run(){ Thread.sleep(1000)//线程休眠1000毫秒,sleep使线程进入Block状态,并释放资源

}}

开启线程:对象.start()//启动线程,run函数运行

(2)实现Runnable接口,重写run函数

开启线程:Thread t = new Thread(对象)//创建线程对象

调用:t.start()

(3)实现Callable接口,重写call函数

Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。 

Callable和Runnable有几点不同:

①Callable规定的方法是call(),而Runnable规定的方法是run(). 

②Callable的任务执行后可返回值,而Runnable的任务是不能返回值的

③call()方法可抛出异常,而run()方法是不能抛出异常的。 

④运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等


4)线程同步方法

分别是synchronized;wait、notify、notifyAll、sleep;


5)创建对象方法:

一、使用new创建对象。 

二、调用Class类的newInstance方法,利用反射机制创建对象。


6)集群session如何共享?

session共享

session不可跨服务器而存在.下面给出几种session共享的解决方案. 

第一种:客户端解决方法.把session加密后存在cookie中,每次session信息被写在客服端,然后经浏览器再次提交到服务器.即使两次请求在集群中的两台服务器上完成,也可以到达session共享.这种解决方法的优点是session信息不用存放在服务器端,大大减轻了服务器的压力.另一个优点是一个session中的两次或多次请求可以在一个群集中的多个服务器上完成,可以避免单端故障.目前,淘宝是采用的这种解决方案. 

第二种:提供一个群集保存session共享信息.其他应用统统把自己的session信息存放到session群集服务器组.当应用系统需要session信息的时候直接到session群集服务器上读取.这种方式具有第一种方式的第二个优点. 

第三种:配置负载均衡服务器,让用户的一个session在一个服务器完成.定时的备份session信息到salve上面.一台服务器down掉后,通过均衡服务器透明把用户的请求转发到群集中的其他服务器上,此时需要从salve上读取备份的session信息. 


7)单例

第一种形式

public class Singleton {

private Singleton(){}

private static Singleton singleton =new Singleton();

public static Singleton getInstance(){

return singleton;

}

}


第二种形式: 

public class Singleton {

private static Singleton instance = null;

public static synchronized Singleton getInstance() {

// 这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     

// 使用时生成实例,提高了效率!

if (instance == null)

instance = new Singleton();

return instance;

}

}


第三种:

public class Singleton {


    private static class SingletonHolder{

        private static Singleton instance = new Singleton();

    }

    

    private Singleton() {

    }


    public static Singleton getInstance() {

        return SingletonHolder.instance;

    }

    

}

第四种:

public enum Singleton {  

      INSTANCE;  

      public static Singleton getInstance(){    return INSTANCE;   }  

}  


8)说出ArrayList,Vector, LinkedList的存储性能和特性

ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。


-------------------------------------------------------------------------------------------------

我们常用的创建一个类的实例(对象)的方法有以下两种:

一、使用new创建对象。 

二、调用Class类的newInstance方法,利用反射机制创建对象。


如果字符串池有就获取,如果没有就创建。new一定会创建对象。

1)String s=new String("abc")创建了几个对象?2个。

2)String str="abc";  毫无疑问,这行代码创建了一个String对象。  

3)String a="abc";  String b="abc";   那这里呢?答案还是一个。  

4)String a="ab"+"cd";   再看看这里呢?答案是三个。


没有登录不能评论