Java基础面试题及答案解析(11)


手写一段单例中的懒汉模式和饿汉模式,并且简单说一下他们的区别
 
懒汉模式:
publicclassLazySingleton{
   //懒汉式单例模式
   //在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢
   
   
   privatestatic LazySingleton intance = null;
    //静态私用成员,没有初始化
   
   privateLazySingleton()
   {
       //私有构造函数
   }
   
   publicstaticsynchronized LazySingleton getInstance()    
   //静态,同步,公开访问点
   {
       if(intance == null)
       {
           intance = new LazySingleton();
       }
       return intance;
   }

}

饿汉模式:
publicclassEagerSingleton {
   //饿汉单例模式
   //类加载较慢,但获取对象的速度快
   
   privatestatic EagerSingleton instance = new EagerSingleton();
 //静态私有成员,已初始化
   
   privateEagerSingleton()
   {
       //私有构造函数
   }
   
   publicstatic EagerSingleton getInstance()    
   //静态,不用同步
   {
       return instance;
   }
}
 
懒汉模式和饿汉模式的比较:
饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全。饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。
 
懒汉模式的特点是加载类时比较快,但是在运行时获取对象的速度比较慢,线程不安全,懒汉式如果在创建实例对象时不加上synchronized则会导致对象的访问不是线程安全的。
 
ArrayArrayList有何区别?什么时候更适合用Array
 
存储内容比较:
Array数组可以包含基本类型和对象类型,ArrayList只能包含对象类型。
Array数组存放的一定是同种类型的元素,ArrayList可以存放任意对象(object的子类)。
 
空间大小比较:
Array的空间大小是固定的,空间不够时也不能再次申请,所以需要事前确定合适的空间大小。
ArrayList的空间是动态增长的,如果空间不够,它会创建一个空间比原空间大的新数组,然后将所有元素复制到新数组中,接着抛弃旧数组。而且,每次添加新的元素的时候都会检查内部数组的空间是否足够。(比较麻烦的地方)。
 
方法上的比较:
ArrayList作为Array的增强版,在方法上比Array更多样化,比如添加全部addAll()、删除全部removeAll()、返回迭代器iterator()等。
 
适用场景:
如果想要保存一些在整个程序运行期间都会存在而且不变的数据,我们可以将它们放进一个全局数组里;但是如果我们单纯只是想要以数组的形式保存数据,而不对数据进行增加等操作,只是方便我们进行查找的话,那么,我们就选择ArrayList
 
而且还有一个地方是必须知道的,就是如果我们需要对元素进行频繁的移动或删除,或者是处理的是超大量的数据,那么,使用ArrayList就真的不是一个好的选择,因为它的效率很低,我们可以考虑选择LinkedList
 
Tomcat服务器优化(内存,并发连接数,缓存)
 
  • 内存优化:主要是对Tomcat启动参数进行优化,我们可以在Tomcat启动脚本中修改它的最大内存数等等。
  • 线程数优化:Tomcat的并发连接参数,主要在Tomcat配置文件中server.xml中配置,比如修改最小空闲连接线程数,用于提高系统处理性能等等。
  • 优化缓存:打开压缩功能,修改参数,比如压缩的输出内容大小默认为2KB,可以适当的修改。
 
多线程中sleep()wait()yield()join()的用法与区别

1.sleep()方法
在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。
sleep()使当前线程进入阻塞状态,在指定时间内不会执行。
 
2.wait()方法
在其他线程调用对象的notifynotifyAll方法前,当前线程处于等待状态。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
 
当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。
 
唤醒当前对象锁的等待线程使用notifynotifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。
 
waite()notify()必须在synchronized函数或synchronizedblock中进行调用。如果在non-synchronized函数和non-synchronizedblock中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
 
3.yield方法
暂停当前正在执行的线程对象。
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
yield()只能使同优先级或更高优先级的线程有执行的机会。
 
4.join方法
等待该线程终止。
等待调用join方法的线程结束,再继续执行。如:t.join();它主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。
 
线程和进程的区别?
 
进程和线程都是一个时间段的描述,是CPU工作时间段的描述,不过是颗粒大小不同。
 
进程是资源的分配和调度的一个独立单元,而线程是CPU调度的基本单元。
同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包括一个线程。

进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束。

线程是轻两级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的。

线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源。

线程有自己的私有属性TCB,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志。

    本站所有文章均来自互联网,如有侵权,请联系站长删除。极客文库 » Java基础面试题及答案解析(11)
    分享到:
    赞(0)

    评论抢沙发

    评论前必须登录!