常见面试题

1,什么是线程安全 (参考书:https://book.douban.com/subject/10484692/)

   如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

2,都说String是不可变的,为什么我可以这样做呢

   String a = "1";

   a = "2";

   答: String  a 表示定义一个字符串对象a ,“1” 是一个字符串常量是不可以变的,“2”也是一个字符串常量是不可以变的,a=“2” 表示 "2" 的引用给了 a。

  

3,HashMap的实现原理

  

  答:HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。

  

4,写出三种单例模式,如果能考虑线程安全最好

  

  第一种(懒汉,线程不安全):

 1  public   class  Singleton {  
 2       private   static  Singleton instance;  
 3      private Singleton (){}   
 4       public   static  Singleton getInstance() {  
 5       if  (instance  ==   null ) {  
 6          instance  =   new  Singleton();  
 7      }  
 8       return  instance;  
 9      }  
10  }  
11 

 

 

这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。

第二种(懒汉,线程安全):

 1  public   class  Singleton {  
 2       private   static  Singleton instance;  
 3      private Singleton (){}
 4       public   static   synchronized  Singleton getInstance() {  
 5       if  (instance  ==   null ) {  
 6          instance  =   new  Singleton();  
 7      }  
 8       return  instance;  
 9      }  
10  }  
11 

这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。

第三种(饿汉):

1  public   class  Singleton {  
2       private   static  Singleton instance  =   new  Singleton();  
3      private Singleton (){}
4       public   static  Singleton getInstance() {  
5       return  instance;  
6      }  
7  }  
8 

这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

第四种(饿汉,变种):

 1  public   class  Singleton {  
 2       private  Singleton instance  =   null ;  
 3       static  {  
 4      instance  =   new  Singleton();  
 5      }  
 6      private Singleton (){}
 7       public   static  Singleton getInstance() {  
 8       return   this .instance;  
 9      }  
10  }  
11 

表面上看起来差别挺大,其实更第三种方式差不多,都是在类初始化即实例化instance。

第五种(静态内部类):

 1  public   class  Singleton {  
 2       private   static   class  SingletonHolder {  
 3       private   static   final  Singleton INSTANCE  =   new  Singleton();  
 4      }  
 5      private Singleton (){}
 6       public   static   final  Singleton getInstance() {  
 7           return  SingletonHolder.INSTANCE;  
 8      }  
 9  }  
10 

 

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。

第六种(枚举):

1  public   enum  Singleton {  
2      INSTANCE;  
3       public   void  whateverMethod() {  
4      }  
5  }  
6 

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。
 

第七种(双重校验锁):

 1  public   class  Singleton {  
 2       private   volatile   static  Singleton singleton;  
 3      private Singleton (){}   
 4       public   static  Singleton getSingleton() {  
 5       if  (singleton  ==   null ) {  
 6           synchronized  (Singleton. class ) {  
 7           if  (singleton  ==   null ) {  
 8              singleton  =   new  Singleton();  
 9          }  
10          }  
11      }  
12       return  singleton;  
13      }  
14  }  
15 

5,ArrayList和LinkedList有什么区别

    答:ArrayList底层是可变数据,查询快,增删慢

          ArrayList底层是链表数据结构,增删快,查询慢

6,实现线程的2种方式

    

    继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程

   

7,JVM的内存结构

   答:堆区,栈区,方法区,寄存器,本地方法区

8,Lock与Synchronized的区别

  答:synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否,而ReentrantLock使用                 代码实现的,系统无法自动释放锁

   

9,数据库隔离级别有哪些,各自的含义是什么,MYSQL默认的隔离级别是是什么。

  答: 数据库的隔离级别:

           ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。(mysql默认)

  ③ Read committed (读已提交):可避免脏读的发生。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

 

 

10,请解释如下jvm参数的含义:

-server -Xms512m -Xmx512m -Xss1024K 

-XX:PermSize=256m -XX:MaxPermSize=512m -XX:MaxTenuringThreshold=20 XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly。

-Xms512m              ( Java能够分配的内存)
-Xmx512m              ( JAVA能够分配的最大内存)
-XX:PermSize=512M      (非堆内存初始值)
-XX:MaxPermSize=512M   (非堆内存最大值)
-XX:ReservedCodeCacheSize=64m  (eclipse缓存)

猜你喜欢

转载自chuichuige.iteye.com/blog/2396216