上海大学计算机研究生面试试题hashMap、hashtable、ConcurrentHashMap、hashset的区别hashMap1)允许空值和空健2)线程不安全,效率高于hashtable3)HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey 3)HashMap中hash数组的默认大小是16,而且一定是2的指数。
4)JDK1.2出现的hashtable1)不允许空健和空值2)线程安全,效率低于hashMap3)HashTable中hash数组默认大小是11,增加的方式是 old*2+13)JDK1.0出现的ConcurrentHashMap1)一个ConcurrentHashMap由多个segment组成,每一个segment都包含了一个HashEntry 数组的hashtable2)每一个segment包含了对自己的hashtable的操作,比如get,put,replace等操作,这些操作发生的时候,对自己的hashtable进行锁定。
由于每一个segment写操作只锁定自己的hashtable,所以可能存在多个线程同时写的情况,性能无疑好于只有一个hashtable锁定的情况,高并发hashset1)只能放入单独的对象2)放入的元素无序3)放入的元素不能够重复4)HashSet 底层采用HashMap 来保存所有元素所有放入HashSet 中的集合元素实际上由HashMap 的key 来保存,而HashMap 的value 则存储了一个PRESENT,它是一个静态的Object 对象。
将一个字符串反转:System.out.println(new StringBuilder("i love you ").reverse().toString());String str="i Love you";List list = new ArrayList();String splitStr []=str.split(" ");list=Arrays.asList(splitStr);Collections.reverse(list);for(String word:list){System.out.print(word+" ");volatile、synchronized、final、wait、notify的含义Volatile:Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。
而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。
这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
volatile是变量修饰符,用在多线程,同步变量。
线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。
只在某些动作时才进行A和B的同步。
因此存在A和B不一致的情况。
volatile就是用来避免这种情况的。
volatile告诉jvm,它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A)在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。
为了性能,一个线程会在自己的memory中保持要访问的变量的副本。
这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况。
一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。
public class StoppableTask extends Thread {private volatile boolean pleaseStop;public void run() {while (!pleaseStop) {// do some stuff...}}public void tellMeToStop() {pleaseStop = true;}}假如pleaseStop没有被声明为volatile,线程执行run的时候检查的是自己的副本,就不能及时得知其他线程已经调用tellMeToStop()修改了pleaseStop的值。
S ynchronized:synchronized获得并释放监视器,如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。
显然synchronized要比volatile消耗更多资源。
F inal:用于修饰变量属性、方法和类修饰变量属性: 如果变量为基本数据类型表示为常量不能修改其值;如果为引用类型表示变量的引用不能指向新的对象修饰方法表示改方法不可重写修饰类表示改类不可继承Wait:wait是Object 类中的方法且不能够被重写wait方法只能放在同步的方法货同步块中,表示资源同步时线程需要等待wait会自动释放对象锁wait方法需要等待线程唤醒后,线程才会继续执行,靠别人来唤醒Notify:线程的通信,用于唤醒线程;这里wait和notify方法必须要与sysnchronized一起使用,也就是wait与notify只针对已经获得对象锁进行操作,从语法角度wait与notify必须在sysnchronized(Obj){}语句块中,从功能上讲wait就是说线程在获取对象后,主动释放对象锁,同时本地线程休眠。
直到有其他线程调用对象的notify方法对对象锁进行唤醒操作,notify调用后并不是马上释放对象锁,而是在相应的sysnchronized语句块执行结束,自动释放后,jvm会在wait对象锁的线程中随机选取一段线程赋予对象锁,唤醒线程继续执行,这样提供了在线程间同步、唤醒的操作.java内存模型并做简要说明。
JVM具有一个堆,堆是运行时数据区域,所有的实例和数组的内存均从这里进行分配,内存中又分为栈、堆、数据段等的概念.内存模型中有主内存和工作内存,类似于电脑中的闪存和高速缓存样,线程使用的数据库在主内存中,然后对数据库的操作,为了获得更快的速度,会放到寄存器和高速缓存中,java类型模型规定所有的变量都存储在主内存中,而工作闪存会放到变量的副本拷贝,线程对所有变量的操作都在工作内存中进行,而且不同的线程不能访问对方工作内存中的变量,只能够通过主内存进行访问.Java线程之间的通信由Java内存模型控制.JMM决定一个线程对共享变量的写入何时对另一个线程可见,Java的并发采用的是共享内存模型.主内存和工作内存之间的具体交互协议,即变量如何从主内存到工作内存,然后又从工作内存回到主内存的实现细节,JAVA 内存模型定义了以下8中操作完成,虚拟机实现时,必须保证下面的每一种操作都是原子的、不可分割的1.lock(锁定) 作用于主内存的变量,它把变量表示成为一条线程独占的状态。
2.unlock(解锁)作用于主内存的变量,它把一个处于锁定状态的变量释放出来,解锁后才能被其他线程锁定3.read(读取):作用于主内存的变量,它把主内存的变量值传输到线程对应的工作内存中,等待load4.load(载入) 作用于工作内存的变量,它把从read操作从主内存中得到的变量值,放入到工作内存的变量副本中。
e(使用) 作用于工作内存的变量,它把工作内存的变量的值传递给执行引擎,每当虚拟机遇到一个需要使用的变量的值的字节码指令时,将会执行这个操作。
6.assigin(赋值) 作用于工作内存的变量,它把一个从执行引擎接收到的值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
7.store(存储) 作用于工作内存的变量,它把工作内存中的一个变量的值传送到主内存中,以便write操作8.write(写入) 作用于主内存的变量,它把store 操作从工作内存中得到的变量值放到主内存变量中。
什么是“异步模型”,与同步模型比有什么优点。
1、如果做一件事情是有顺序的,先做完Task1,再做Task2,最后做Task3,这类事情也是我们日常见的最多的一种情况2、如果做一件事情并没有顺序之分,可以同时进行,每一件事情也是相对独立的,其实这就是一种同步模型。
当然,其实这也是一种理想情况,在大多数情况下,进程之间或线程之间往往要进行通信,一个任务会等待另外一个任务的返回结果,这就有些较为复杂了3、在异步模型中,任务是交替运行的,但仍然在一个进程中,其中每个任务的运行状态都是可以被我们控制的异步模型与同步模型有什么区别吗?a) 同步模型中的任务交替运行,是需要多个线程协同完成的,受到程序的控制,而在异步模型中则不需要。
b) 多线程本身就受到操作系统的调度与管理,所以同步模型本身就受到操作系统控制的,而在异步模型中一个任务会一直运行下去,直到任务被运行完或者程序暂停这个任务而去执行令一个任务c) 异步模型比同步模型简单,因为异步模型只有一个进程而且任务的停止和运行状态是可控的。
而在同步模型中,我们需要把每一个任务分成很多步骤,然后再有序的把他们组合起来d)如果程序中会有阻塞、被强迫等待等情况,异步模型会比同步模型运行速度快, 异步程序设计的原理就是当其中一个任务被阻塞的时候,可以先去执行一些其他可以执行的任务所以一个异步程序也会被叫做“无阻塞程序”。
那什么时候,我们需要考虑使用异步模型呢?a) 有很多任务,经常总有一个任务可以继续执行b) 这些任务中要执行很多I/O操作c) 这些任务大多都是独立的列举你常用的模式,重点说明观察者模式。
单例模式、工厂模式、观察者模式又称作”发布—订阅”模式。
定义了一种一对多的依赖关系. 让多个观察者对象同时监听某一个主题对象, 这个主题对象在状态发生变化的时候,会通知所有的观察者对象,使他们能够自动更新自己。
什么时候使用:当一个对象的改变需要同时通知其他对象的时候, 而且它不知道具体有多少对象需要通知的时候,需要通知的对象能够动态地增加为什么要使用观察者模式?交互对象之间的松耦合设计使得观察者和主题之间达到一个松耦合。
观察者模式的组成:观察者模式的静态结构中包含这样一些角色:1)抽象主题角色subject:2)抽象观察者角色Observer3)具体主题角色(concreteSubject)4)具体观察者(ConcreteObserver)角色什么时候会产生outofmeoryErrorException,并说明产生原因。