点击上方“ Java知音 ”,选择“置顶公众号”
技术文章第一时间送达!
知音专栏
Javaweb练手项目源码下载
常用设计模式完整系列篇
100套IT类简历模板下载
Java常见面试题汇总篇
public class LazySingleton { //懒汉式单例模式 //在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢 private static LazySingleton intance = null; //静态私用成员,没有初始化 private LazySingleton() { //私有构造函数 } public static synchronized LazySingleton getInstance() //静态,同步,公开访问点 { if(intance == null) { intance = new LazySingleton(); } return intance; } }
public class EagerSingleton { //饿汉单例模式 //类加载较慢,但获取对象的速度快 private static EagerSingleton instance = new EagerSingleton(); //静态私有成员,已初始化 private EagerSingleton() { //私有构造函数 } public static EagerSingleton getInstance() //静态,不用同步 { return instance; } }
饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全。饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。
懒汉模式的特点是加载类时比较快,但是在运行时获取对象的速度比较慢,线程不安全, 懒汉式如果在创建实例对象时不加上 synchronized 则会导致对象的访问不是线程安全的。
Array 和 ArrayList 有何区别?什么时候更适合用 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() 的用法与区别
在指定时间内让当前正在执行的线程暂停执行,但不会释放 “锁标志”。不推荐使用。
sleep() 使当前线程进入阻塞状态,在指定时间内不会执行。
在其他线程调用对象的 notify 或 notifyAll 方法前,当前线程处于等待状态。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出 IllegalMonitorStateException 异常。
唤醒当前对象锁的等待线程使用 notify 或 notifyAll 方法,也必须拥有相同的对象锁,否则也会抛出 IllegalMonitorStateException 异常。
waite() 和 notify() 必须在 synchronized 函数或 synchronized block 中进行调用。如果在 non-synchronized 函数和 non-synchronized block 中进行调用,虽然能编译通过,但在运行时会发生 IllegalMonitorStateException 的异常。
暂停当前正在执行的线程对象。
yield() 只是使当前线程重新回到可执行状态,所以执行 yield() 的线程有可能在进入到可执行状态后马上又被执行。
yield() 只能使同优先级或更高优先级的线程有执行的机会。
等待该线程终止。
等待调用 join 方法的线程结束,再继续执行。如: t.join(); 它主要用于等待 t 线程运行结束,若无此句, main 则会执行完毕,导致结果不可预测。
线程和进程的区别?
进程和线程都是一个时间段的描述,是 CPU 工作时间段的描述,不过是颗粒大小不同。
进程是资源的分配和调度的一个独立单元,而线程是 CPU 调度的基本单元。
同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包括一个线程。
进程的创建调用 fork 或者 vfork ,而线程的创建调用 pthread_create ,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束。
线程是轻两级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的。
线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源。
线程有自己的私有属性 TCB ,线程 id ,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块 PCB ,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志。