笔试面试题二

31出现OOM异常怎么解决

OOM是什么:OUT OF MEMORY

OOM为什么出现:内存空间不足,至于哪的内存可能是堆的,可能是

OOM怎么解决:一般就是设大点。


类似的还有StackOverFlowError
当线程请求的栈深度大于虚拟机所允许的最大栈深度,就会抛出这个异常。

方法区物理上存在于堆里,而且是在堆的持久代里面;但在逻辑上,方法区和堆是独立的。
一般说堆的持久代就是说方法区,因为一旦JVM把方法区(类信息,常量池,静态字段,方法)加载进内存以后,这些内存一般是不会被回收的了。

永久代也就是我们通常说的方法区。 
java8从Hotspot JVM中删除了永久代,所以我们不再需要为永久代设置大小,也就是不用设置PermSize和MaxPermSize。 
在java8之前方法区是作为堆的永久代来实现的,启动JVM时我们需要设置永久代的大小,垃圾回收器也要回收这部分区域,而且会抛出内存溢出异常。借鉴于JRockit虚拟机,java8之后 Hotspot 虚拟机从堆中彻底删除了永久代。 
—把方法区中的String和静态变量移到了堆中。 
—把其他的东西(比如类结构)放到了本地内存中,JVM会直接负责这部分的内存回收。

总之,我们不再需要设置PermSize和MaxPermSize;方法区的内存溢出将不再出现,除非本地内存耗光。

32单例模式,工厂模式和统计一个数组里出现次数超过一半的数

一、懒汉式单例

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. //懒汉式单例类.在第一次调用的时候实例化自己   
  2. public class Singleton {  
  3.     private Singleton() {}  
  4.     private static Singleton single=null;  
  5.     //静态工厂方法   
  6.     public static Singleton getInstance() {  
  7.          if (single == null) {    
  8.              single = new Singleton();  
  9.          }    
  10.         return single;  
  11.     }  
  12. }  

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题:


1、在getInstance方法上加同步

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static synchronized Singleton getInstance() {  
  2.          if (single == null) {    
  3.              single = new Singleton();  
  4.          }    
  5.         return single;  
  6. }  

2、双重检查锁定

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public static Singleton getInstance() {  
  2.         if (singleton == null) {    
  3.             synchronized (Singleton.class) {    
  4.                if (singleton == null) {    
  5.                   singleton = new Singleton();   
  6.                }    
  7.             }    
  8.         }    
  9.         return singleton;   
  10.     }  

3、静态内部类

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. public class Singleton {    
  2.     private static class LazyHolder {    
  3.        private static final Singleton INSTANCE = new Singleton();    
  4.     }    
  5.     private Singleton (){}    
  6.     public static final Singleton getInstance() {    
  7.        return LazyHolder.INSTANCE;    
  8.     }    
  9. }    
这种比上面1、2都好一些,既实现了线程安全,又避免了同步带来的性能影响。


就记住工厂方法是一个工厂创建一种产品,抽象工厂是一个方法创建多个商品。

//出现次数大于一半,意味着肯定有挨着的两个数
		int[] i = new int[]{8,1,1,8,8,8,3,3,5,8,6,7,8,8,8,8,1,2,8};
		//先考虑如果是奇数数组如果中间没有挨着的首尾肯定相等
		if(i[0] == i[i.length-1]){
			int times = 0;
			for(int p=0;p<i.length;p++){
				if(i[p] == i[0]){
					times ++;
				}
			}
			if(times > i.length /2){
				System.out.println(i[0]);
			}
		}else{
			for(int j = 0 ;j < i.length - 1; j ++){
				if(i[j] == i[j + 1]){
					int times = 0;
					for(int p=0;p<i.length;p++){
						if(i[p] == i[j]){
							times ++;
						}
					}
					if(times > i.length /2){
						System.out.println(i[j]);
						break;
					}
				}
			}
		}


33高并发下的优化手段

那要看瓶颈在哪了,是数据库就去优化数据库,如果数据库瓶颈在IO还要加强硬件,如果性能瓶颈就要负载均衡,拆表之类,HTML静态化,利用NGINX,CDN等,如果是分布式直接的互通也是IO吧还要看用什么实现的,如果发的内容大甚至可以压缩了传。系统性能用缓存,软件集群数据库集群等了。

http://www.ablanxue.com/prone_1020_1.html

CDN:内容分发网络,你可以理解为一切为了用户体验,为了用户更快的打开网页,把常用资源放在离用户最近的节点,CDN就是做的这个工作。

HA:High Availability Cluster,简称HACluster

  具体HA衡量标准:
99% 一年宕机时间不超过4天

99.9% 一年宕机时间不超过10小时

99.99% 一年宕机时间不超过1小时

99.999% 一年宕机时间不超过6分钟


一想到我们公司的系统,呵呵呵呵呵呵


 在集群服务器架构中,当主服务器故障时,备份服务器能够自动接管主服务器的工作,并及时切换过去,以实现对用户的不间断服务。

http://aokunsang.iteye.com/blog/2053719


分布式系统中还有一个问题就是SESSION共享http://www.cnblogs.com/yanweidie/archive/2015/08/17/4678095.html

可以放在REDIS中,

34jstack(查看线程)、jmap(查看内存)和jstat(性能分析)命令

http://guafei.iteye.com/blog/1815222


35JS作用域

http://www.studyofnet.com/news/294.html

简单说就是如果没有显示指定的就是全局变量,如果显示指定了看位置如果在方法里就是私有变量,根据作用域链,私有变量找到后就不会向上查找了。


36spring的annotation

注解 1简化配置 2自定义操作

简化配置好理解,自定义操作就是像公司项目做了分表,在执行SQL的时候自动找到对应的表。


37用java语言打印出a,b,c,d的所有可能组合

static int c = 1;

	public static void main(String[] args) {
		String s = "abcde";
		printAllArray(s, "");
	}


	private static void printAllArray(String s, String n) {
		if (s.length() == 0) {
			System.out.println(n + "  ---  " + c++);
		} else {
			for (int i = 0; i < s.length(); i ++) {
				System.out.println(s.substring(1) + ":" + (n + s.charAt(0)));
				printAllArray(s.substring(1), n + s.charAt(0));
				s = s.substring(1) + s.charAt(0);
			}
		}
	}
38哈希一致性、ZK等知识
Zookeeper主要可以干哪些事情:配置管理,名字服务,提供分布式同步以及集群管理.

http://blog.csdn.net/yoara/article/details/45308937 ZOOKEEPER使用了观察者模式

JNDI是把数据源配置在文件中,减少了代码和配置的耦合。

哈希一致性算法是用于解决服务器均衡问题,http://blog.csdn.net/caigen1988/article/details/7708806

consistent hashing 是一种 hash 算法,简单的说,在移除 / 添加一个 cache 时,它能够尽可能小的改变已存在 key 映射关系,尽可能的满足单调性的要求。


39Cookie和Session的区别和优缺点

首先COOKIE是存在客户端的,而SESSION是存在服务器端的。cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。cookie可以存在内存和硬盘里,存储和清除的策略由浏览器实现。

单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie

http://www.cnblogs.com/shiyangxt/archive/2008/10/07/1305506.html

http://www.admin10000.com/document/1034.html


40类似京东商城网站设计需要注意些什么

首先肯定是安全性,高并发,稳定性这些,包括首页的载入速度,搜索查询速度的优化。


41Java中的switch语句的参数

能转为INT的 包括char,byte,short,int,后来支持了STRING和ENUM,但是STRING的字节码发现是用HASHCODE比的,还是INT的比较


42Java中线程安全的机制,如何实现?实现方式?yeild的方法的使用?会释放锁吗?线程死锁?

线程安全就是同步,保证当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替运行,并且在主调试代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,则称这个类时线程安全的。同步就用到了SYNCHRONIZED以及CONCURRENT包。

yeild就是让当前线程停止运行等待CPU召唤,也可能立刻被召唤了,

释放锁就看你是隐式还是显式了,CONCURRENT包里很多类如果显式上锁了就需要你显式释放掉。隐式就是代码块执行完了自动释放。

线程死锁就是两个线程等待同一份资源,

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

http://www.cnblogs.com/Jessy/p/3540724.html


43Java中内存泄露有几种?如何分析泄露原因

内存泄露我们都知道是OOM,可能产生的原因有

1)静态集合类引起

2)各种连接比如数据库连接

3)监听器

4)内部和外部的引用

5)单例模式对外部资源的引用

等。

首先用分析工具DUMP,

Dump的本意是"倾卸垃圾"、"把(垃圾桶)倒空"。在计算机技术中使用Dump的主要意思仍 
然如此,即当电脑运行发现故障后,无法排除而死机,通常要重新启动。为了找出故障的原因 
,需要分析现场(即死机时整个内存的当前状况),在重新启动系统之前要把内存中的一片0、 
1(这时它们尤如一堆垃圾)"卸出"保存起来,以便由专家去分析引起死机的原因。技术资料中 
把这个"卸出"的过程叫dump;有时把卸出的"内容"也叫dump。

这种工具很多比如JMAP,然后分析哪些数据量太大了,比如char[]太多了就可能有大STRING对象,然后找到谁引用的,

http://blog.sina.com.cn/s/blog_644eb93501012jje.html 比如文中的问题,实际就需要StreamTokenizer来代替split


44IOc如何实现依赖注入的?Spring动态代理的实现方式?

依赖注入:常用的就是SET注入和构造器注入


AOP有两种配置方式,注解和文件配置,我在工作中平时用的是文件配置。

JDK自带的动态代理

一个动态代理类实现了INVOCATIONHANDLER接口  有个BIND方法返回创建好的代理对象  执行该对象自己的方法即可。

但是该方法有个缺陷,仅能针对有接口的类,所以针对没有接口的类有了CGLIB,原理是对指定类生产一个子类,覆盖其中的方法

1:如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2:目标对象实现了接口,可以强制使用CGLIB实现AOP

3:如目标对象没有实现接口,必须采用CGLIB库,spirng会自动在JDK动态代理和CGLIB之间转换

http://www.tuicool.com/articles/3AzAnuA CGLIB性能高但是创建时间长,对于FINAL的类和方法由于不能继承无法使用CGLIB


45索引什么时候会失效?

关于索引的使用和其数据结构(B,B+树,就是个查找问题)前面都说过,

何时会失效:1条件中有OR且OR的左右并没有都建立索引时2多列索引3like查询以%开头4索引列进行了数学运算5根据索引的不同比如B树索引位图索引,对IS NULL ISNOT NULL的支持不一样6查询小表或者返回值大于10%

http://blog.csdn.net/colin_liu2009/article/details/7301089 这里很全


46Java的Object类中的方法及其作用

equal(内部用的==),hashcode,tostring(会把名字和HASHCODE一起打出来)


47Java中 volatile关键字的含义及其使用方法?

在HOTSPOT中,用volatile修饰的变量不会再线程中保存副本,而是直接指向堆中的引用,他比synchronized快十几倍。

volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。


48拦截器

http://struts2.group.iteye.com/group/wiki/1397-deep-into-struts2-interceptors


49简述一下常用的一些算法和其时间复杂度?冒泡、选择、插入、位排序、堆排序、快速排序、二分法排序等?

这个就是个大工程了,包括每个算法最优和最差平均的时间复杂度以及具体实现的代码。

排序:空间复杂度  时间复杂度 是否稳定

1冒泡:最好On 最坏On2 1个额外空间 稳定

2选择:On2   P1 不稳定

for(int i = 0;i < size -1; i ++){

for(int j = i+1;j<size;j++ ){

data[i]  data[j] 比较,交换

}

}

冒泡和选择每一轮的结果看上去都是选出了个大的,其他的看情况顺移了,但是实际上冒泡每次都会进行交换,可能最多进行了N次交换,他是顺序的交换。

而选择是针对2个比较交换,如果不满足条件就不会交换。所以选择比冒泡快。

3插入排序:On On2 P1 稳定

for(int i = 0;i < size;i ++){

tmp=data[i];

j = i -1;

while(j >= 0 && tmp>data[j]){

data[j+1] = data[j];

j --;

}

data[j + 1] = tmp;

}

第一次会出现data[-1 + 1] = data[0],注意换的时候是用前面的那个数给后面的数!!是前给后!

比如2 5 6 9

2 5 6 9

2 2 6 9

5 2 6 9

5 2 2 9

5 5 2 9

6 5 2 9

不像冒泡和选择,把那个数放在里面来回倒,直接拎出来,让要移动的数创建个分身到拎出来的数之前的位置,再把拎出来的数替换掉原来分身的数,也就是那个数就只有分身没有原版了。

4希尔排序 On3/2 P1 稳定 适用于大部分数据都已排序完成的情况下

jump = size /2

while(jump != 0){位移间隔 不断/2到0为之

for(int i = jump; i <size; i ++){//一定注意!!这里I=JUMP!!!

tmp=data[i];

j = i - jump;

while(j>=0 && tmp>data[j]){

data[j + jump] = data[j] 后面的等于前面的!

j = j - jmp  这里很巧妙 和下面的话完成了最后的赋值,因为是前面赋值给后面,最后的值又要给前面不能少值,这么处理后就在下面赋值了

}

data[jmp + j ] = tmp  这里很巧妙

}

jump = jump/2

}

比如4个数,JUMP开始为2  【2 5 6 9】

tmp =data[i] =  6 

i=jump = 2

j = i - jump = 0

因为j>0且tmp >data0

data0 + 2 = data[0] 

J = J- JUMP = -2

data 2+ j = data 2 + -2  赋值为tmp = 2


2569 - 2529  -6529这才是FOR循环中的一次

然后是i= 3了,会一直增加到SIZE-1,不会有漏的情况,如果是奇数个就会变成3个一组了,反正是从后面往前按照JUMP比较的,前面的数组第 1 3项比较完已经有序了,第5项加进来比较没有任何问题,以此类推


5合并排序 ONLOGN PN 稳定

6快速排序 ONLOG2N-ON2 PN-PLOG2N 不稳定,平均运行时间最快的排序,没有之一。

关键在于K的取值,不能太大也不能太小。

WHILE(TRUE){

int K = data【0】

for()左到右找到比K大的KI

for(int i = left + 1;i < right i ++){

if K < KI

break

leftINDEX = I

}

FOR右到左找到比K小的KJ,如果I<J则I J互换 继续左右两头查找

FOR(INT J = RIGH; J > LEFT ; J --){

IF KJ < K

BREAK

   RIGHTINDEX = J

}

IF(LEFTINDEX < RIGHTINDEX ){

KI KJ互换

}ELSE{

BREAK;

}

}

K KJ互换 ;

以RIGHTINDEX为基点分为两部分,也就是不包括KJ这个点,注意现在这个点放的其实是之前K的值了

QUICKSORT(INT D[];SIZE;LEFT;RIGHTINDEX-1);

QUICKSORT(INT D[];SIZE;RIGHTINDEX + 1;传到这个方法里的RIGHT的值也就是最右边的INDEX);


如果I >= J 则 K与KJ互换,用J分割数组为两部分,递归方式分别进行快排。

所以需要的参数为 1数组,2大小,3参数1这次要排序的起止位置



}


7堆积排序ONLOGN  P1 不稳定 

下面想的八成应该是错误的,因为看起来就是一个插入排序,只不过为了维持树还要多移动比较几次。跟堆排序的效率完全是相反。只能叫如何构成完美的堆积数,是完美的,效率还很低的那种。




虽然这里没看明白,但是基本道理还是懂的。

需要一个堆积树,那么就有一个根据数组元素一个一个插入构成堆积树的过程。

构成后顶点的就是最大值,把他拿下来放到树的最后一一个位置,把其他的值再一个一个插入构成一个堆积树,再取下树顶,依次循环这个过程就可以了。

所以关键就是构成堆积树的过程。

插入的过程去想嘛,一个数肯定就是树顶,第二个数比较跟第一个数交换或者放在左1,第三个数跟左1比看互换还是放在右1,互换后再跟顶比,也就是从最下面的右叉开始一个一个比,因为前面的都已经排好序了,第四个再跟右1比,换或者放在左2,所以放在左叉的是第2468.。。这样的偶数,右叉是3开始的奇数。一直在最左侧的,是24816这样每次乘2的结果因为每个节点都会分叉嘛,自然X2.


那么插入的过程 INSERTINTOTREE(DATA[N])

if tree.size 

上面说了最左叉是2 4 8 16这样的数  2开始的偶数和他紧挨着的奇数都在一个节点。那就看这个树你用数组是怎么表示了,如果按照顺序1开始到最后就把新加的数从最后一个开始比,直到比他小的数截止,让他和最后一个比他大的数互换,再让那个数作为新的值插入!!!!!!

1 1

2 1< <3

3 3< <8




8基数排序 ONLOGPK  K是最大值 P是最大值位数  PN*P N是数据个数 P前面说了是最大值位数 当N很大而P很小时,会很高效。稳定排序

基数排序利用的就是0-9  10个桶因为每个桶可能放的数不确定,所以初始化这个数组可以为[10][N] 也就是二维数组10行 每行最多数组大小的数应付极端情况

第一次根据个位数把数放进桶里,然后从0-9的10个桶依次取其中不为0的数放进原来的数据,因为原来的数组里的数就没有0,所以如果带0,这个数组就可以初始化为都是-1这样的极端情况。

第二次根据十位数把数放进桶,再放回去,如果还有百位就继续这样。






50wait notity  notifyall 


可以说这3个都是针对对象的,而不是线程的方法,属于OBJECT,而且他们都需要在同步代码块中去执行,WAIT顾名思义把对当前资源的占用让出去,直到被人NOTIFY了他才会继续运行。

这里就要切记一点。线程的同步就是一个加解锁的过程,锁的是什么?看你需要就锁什么。只有持有对相同对象的锁的线程之间,才是同步关系,不同对象的锁互不影响!!

http://www.jb51.net/article/56440.htm

而这个锁对象可以有这么几种:

1类锁,STATIC SYNCHRONIZE 与 FOO.CLASS

2对象锁 SYNCHRONIZE与THIS

3私有锁:都对一个OBJECY同步代码块

也就是这几种锁中是一样的锁对象,他们的代码就会阻塞。


51join yiele

http://www.tuicool.com/articles/BF7Bfq

JOIN就是一个线程A创建好后,把它传入另一个线程B,在B中调用A.JOIN,就会先执行完A再继续执行B。

YIELD相反,也是A传入B,B执行过程中A.YIELD,这时候A就不执行了,等B执行完再执行A。

以上两个方法在特定场景下,什么时候谁优先很重要。


52生产者 消费者模型

http://blog.csdn.net/luohuacanyue/article/details/14648185

也是ACTIVEMQ的基础,竟然用的就是上面的WAIT,NOTIFY,

在说WAIT NOTIFY时我们知道他们共有引用了一个变量,这个变量在P-C中可能就是仓库,直到仓库有东西了,才会NOTIFY去处理,处理完没东西了,继续WAIT。

实际实现过程中还是会遇到很多问题,所以也有一些现成的解决方案:

多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内,万一发生数据处理速度不匹配的情况呢?理想情况下,如果生产者产出数据的速度大于消费者消费的速度,并且当生产出来的数据累积到一定程度的时候,那么生产者必须暂停等待一下(阻塞生产者线程),以便等待消费者线程把累积的数据处理完毕,反之亦然。然而,在concurrent包发布以前,在多线程环境下,我们每个程序员都必须去自己控制这些细节,尤其还要兼顾效率和线程安全,而这会给我们的程序带来不小的复杂度。好在此时,强大的concurrent包横空出世了,而他也给我们带来了强大的BlockingQueue。(在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒)

http://blog.itpub.net/143526/viewspace-1060365/

先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。
  后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。


concurrent包太屌了,很多东西都有了1.5加入的

countdownlatch 

http://www.importnew.com/15731.html

CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。



53大数据排序?

大数据排序也就是要用到我们说的外部排序,常见的就是归并排序,分成小块再组合,思想是分治法。

http://www.cnblogs.com/springsource/archive/2013/03/20/2970913.html


54数据分组查询后取前几条记录的SQL

语法:ROW_NUMBER() OVER(PARTITION BY COLUMNX ORDER BY COLUMNY)

http://jingyan.baidu.com/article/9989c74604a644f648ecfef3.html partition分隔的意思
先把需要排序的列排序,然后对结果加个序号,PARTITION BY COLUMNX 表示对X列分组,ORDER BY自然就是根据Y列排序,X,Y可以为相同列。用此函数计算后的就是编号了。


56网络7层协议,TCP3次握手4次挥手

我要连了。你连吧。好的我连上了。

我要断开了。我知道了。你断开吧。我断开了。
多了一个表示知道了的过程。
OSI网络协议,一共七层。
最下面一层是物理层,关心的是接口,信号,和介质,只是说明标准,如EIA-232接口,以太网,fddi令牌环网
第二层是数据链路层:一类是局域网中数据连路层协议:MAC子层协议,有LLC子层协议.另一类是广域网的协议如:HDLC,PPP,SLIP.
第三层是网络层:主要是IP协议.
第四层是传输层:主要是面向连接的TCP传输控制协议.另一个是不面向连接的UDP用户数据报协议.
第五层是会话层:主要是解决一个会话的开始进行和结束.(真的想不起有什么协议)
第六层是表示层:主要是编码如ASⅡ 
第七层是应用层,就是应用程序里面的拉,文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等。 HTTP协议(Hypertext Transfer Protocol,超文本传输协议)是用于从WWW服务

57WeakHashMap是否使用过?其特性?
WeakHashMap,此种Map的特点是,当除了自身有对key的引用外,此key没有其他引用那么此map会自动丢弃此值,
见实例:此例子中声明了两个Map对象,一个是HashMap,一个是WeakHashMap,同时向两个map中放入a、b两个对象,当HashMap  remove掉a 并且将a、b都指向null时,WeakHashMap中的a将自动被回收掉。出现这个状况的原因是,对于a对象而言,当HashMap  remove掉并且将a指向null后,除了WeakHashMap中还保存a外已经没有指向a的指针了,所以WeakHashMap会自动舍弃掉a,而对于b对象虽然指向了null,但HashMap中还有指向b的指针,所以
WeakHashMap将会保留
http://www.jb51.net/article/36948.htm
要注意一点,就是实际他不会自动释放内存,而是在有外部访问的时候都会调用内部的方法去清除只有自己引用的对象。
注意1:null 值和 null 键都被支持。
注意2:不是线程安全的。
注意3:迭代器的快速失败行为不能得到保证。
注意4:WeakHashMap是无序的。
注意5:确保值对象不会直接或间接地强引用其自身的键,
再深入就是他涉及到强弱引用的概念了
强引用就是正常引用,弱就是WEAKHASHMAP这种,软引用由JVM判断需不需要回收,


58什么是AJAX,为什么要使用Ajax?谈一下你对Ajax的认识?
首先说为什么肯定是为了异步交互的页面用户体验了。
Ajax不是一种技术。实际上,它由几种蓬勃发展的技术以新的强大方式组合而成。Ajax包含:

* 基于XHTML和CSS标准的表示;
* 使用Document Object Model进行动态显示和交互;
* 使用XMLHttpRequest与服务器进行异步通信;
* 使用JavaScript绑定一切。 

这非常好,但为什么要以Ajax命名呢?其实术语Ajax是由Jesse James Garrett创造的,他说它是“Asynchronous JavaScript + XML的简写”。

好了这里既然说是一组技术,那么JSONP也可放在内了。


59java的内存模型
JMMJAVAMEMORYMODEL
之前提过,这里再着重说一遍。
首先JMM和java内存里的堆栈啊永久代什么的不是一个层次的。
1JMM规定了同步性,也就是并发性
2重排序
3原子性,和第一的不谋而合,非原子就会有一致性问题

快速失败:迭代VECTOR时,又启动了线程去修改,这是迭代就会爆出异常,并且中止。因为是半路中止而不是迭代完了才报错,所以叫快速失败。

Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给 自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。

这段说的好,堆是给程序员用的,存的是对象什么的,非堆给JVM用的,放的方法信息啊,类信息这是永久代。当创建了线程就会有方法栈,当方法执行时就生成了栈帧。 然后就是所谓的本地方法区了。

栈帧由三部分组成:局部变量区,操作数栈和帧数据区。 局部变量区和操作数栈要视对应的方法而定,它们是按照字长计算的。

 

局部变量区: java栈帧的局部变量区被组织为一个以字长为单位,从0开始计数的数组。字节码指令通过从0开始的索引来使用其中的数据。类型为int,float,reference和returnaddress的值在数组中只占一项,而类型为byte,short和char的值在存入数组前都将被转换为int。但是long和double类型在数组中却占据连续的两项。

 

操作数栈和局部变量区一样。也被组织成一个以字长为单位的数组。但是不是通过索引来访问,而是通过标准栈操作--压栈和出栈来访问。

 

不同于程序计数器,java虚拟机没有寄存器,程序计数器也无法被程序指令直接访问。java虚拟机是由操作数栈而不是从寄存器中取得操作数的,因此它的运行方式是基于栈的而不是基于寄存器的。

 

虚拟机把操作数栈作为它的工作区--大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈



60hashmap,hashtable虽然写过几遍了还是要写,这次看到一个很详细的文章
http://www.cnblogs.com/devinzhang/archive/2012/01/13/2321481.html

第一,继承不同。

public class Hashtable extends Dictionary implements Map
public class HashMap  extends AbstractMap implements Map

第二

Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

第三

Hashtable中,key和value都不允许出现null值。

在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

第四,两个遍历方式的内部实现上不同。

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

第五

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

第六

Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。 



每组前几条记录的SQL写

每组前几条记录的SQL写

每组前几条记录的SQL写

每组前几条记录的SQL写




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值