java复习

第一:HashMap相关

1.       介绍hashset

   hashset底层是个哈希表,

   构造函数:空构造调用了map的空构造默认初始容量是16,也就是16个水桶(其实就是16个数组),加载因子是0.75倍。

   重写equals方法的之前还要重写hashcode方法,hashcode方法在不重写的时候表示内存地址,重写之后表示一个常量和一个变量经过运算后得到到整数值。

   需要重写hashcode方法和equals方法(两个方法都是比较属性值,hashcode方法是比较部分属性值,equals比较全部属性值),重写hashcode方法的目的是为了决定这个对象在哪个桶中保存。重写equals方法是为了判断他们是否需要添加到集合中。

   例如:hashcode方法比较的结果一样(说明要将对象保存在一个桶中),而equals方法比较两个对象的结果不一样(说明确实需要保存这个对象)。

 

 

2.           LinkedList:底层是单向链表。

   :链表里面的每个小内存空间不一定是连续的(上面两个实现类的每个空间都是连续的)。链表中每个元素都包含两个内容(一个是该空间的内容,另一个是下一个空间的地址,这就保证了空间不用连续)

   栈结构:先进后出,体现的就是LinkerList的开头和结尾的应用(这里也体现出他特有的方法)。多出来的方法是addFirst,addLastgtFirstgetLastremovfFirst等。

3.       介绍hashmap

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

   简化成自己的理解:Hashmap是个kv格式的集合,kset集合(而且是hashset,因此底层是数组,有16个桶),vlist集合(而且是linkedlist,而且是单向链表)。因此hashmap的底层是数组+链表。

4.       hashmaptreemaphashtable的区别

    treemap是有序的,HashMapHashTable是无序的。

   Hashtable的方法是同步的(因此线程安全,效率低),HashMap的方法不是同步的(因此线程不安全,效率较高)

   除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。

   Hashtablehash数组默认大小是11,增加的方式是 old*2+1HashMaphash数组的默认大小是16

   Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好.

   ConcurrentHashMap是多线程的,其中每个线程都是hashtable,因为hashtable是线程安全的,因此ConcurrentHashMap也是线程安全的。

 

 

 

 

 

第二:synchronizedsing各耐z)和lock(唠可)的区别与作用场景。(lock(安唠可))

1.       一个程序最少需要一个进程,而一个进程最少需要一个线程。关系是线程–>进程–>程序的大致组成结构。所以线程是程序执行流的最小单位,而进程是系统进行资源分配和调度的一个独立单位。

2.       同步的实现当然是采用锁了,java中使用锁的两个基本工具是synchronized Lock

 

3.       线程安全:

   线程安全(线程同步):线程切换具有随机性,有时候线程正在执行一半就切换了,这样就不同步了。

   临界区资源:多个线程共享的资源(一段代码,数据),线程同步就是对临界区资源进行保护

   线程同步的原理:给临界区资源加锁。

4.       Synchronizedsing可耐z)介绍:

   同一时刻不管是读还是写都只能有一个线程对共享资源操作,其他线程只能等待

   锁的释放由虚拟机来完成,不用人工干预,不过此即使缺点也是优点,优点是不用担心会造成死锁,缺点是由可能获取到锁的线程阻塞之后其他线程会一直等待,性能不高。

   Synchronized是给对象加锁,两种方式:同步方法,同步代码块。

5.       Lock(辣可)实现和synchronized不一样,后者是一种悲观锁,它胆子很小,它很怕有人和它抢吃的,所以它每次吃东西前都把自己关起来。而Lock呢底层其实是CAS乐观锁的体现,它无所谓,别人抢了它吃的,它重新去拿吃的就好啦,所以它很乐观。

6.       .synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
.lock:需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对象才能保证锁的生效。且在加锁和解锁处需要通过lock()unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

7.       Synchronizedjava关键字,lockjava中的类。

8.       看网站:http://www.dataguru.cn/java-865023-1-1.htmlhttps://blog.csdn.net/u012403290/article/details/64910926?locationNum=11&fps=1

9.       两种锁的区别:https://www.cnblogs.com/handsomeye/p/5999362.html

这个网页下面有很多其他资源:http://zzhonghe.iteye.com/blog/826162

 

 

 

 

 

 

第三:多线程问题

1.       实现runnableruanbo)接口,重写run方法

2.       继承Thread(死ruai的)类,重写run方法。

3.       两个人针对一个账号,因为属性需要共享,因此用接口,(因为用接口,在创建对象的时候只需创建一个)

4.       生命周期:start,运行态,wait,等待态,notify,唤醒态,阻塞态(死锁)

其实就是:新建态、就绪态、运行态、阻塞态、死亡态

 

 

 

 

第四:单例模式步骤

        1.要求:只存在该类的一个对象

        第一步:将构造函数私有化(这样的目的是只有本类自己能够产生我自己的对象,别人不能创建我。也就是说别人无法下载)

        第二步:声明一个私有的静态变量

        第三步:创建一个对外公共的静态方法访问该变量,如果变量没有对象,就创建该对象。

   2.代码如下:

private static Single s = new Single();//2.别人不能创建这个类的对象,自己给自己创建对象

        private Single()//1.这个类的对象不能随便创建,只能本类创建

        {

                

        }

        public static Single getInstance()//3.获取私有属性的值,用属性Single get方法

        {

                 return s;

        }

 

        public String getStr()

        {

                 return this.str;

        }

        public void setStr(String str)

        {

                 this.str=str;

        }

 

        public void read()

        {

                 this.str="只存在该类的一个对象";

        }

 

 

 

10.   Concurrent(肯卡润的)

11.   Concurrenthashmaphashmap的区别:他们两个都是16个桶,但是hashmap 是线程不安全的。Concurrenthashmap是线程安全的,操作的时候只需要锁住当前的桶即可。

12.   Concurrenthashmaphashtable的区别:他们都是线程安全的,hashtable在操作的时候是锁住整个结构。Concurrenthashmap是锁住一个桶,效率更高。

13.HashTable里使用的是synchronized关键字,这其实是对对象加锁,锁住的都是对象整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。ConcurrentHashMap引入了水桶(Segment),上面代码中的最后一行其实就可以理解为把一个大的Map拆分成N个小的HashTable,在put方法中,会根据hash(paramK.hashCode())来决定具体存放进哪个Segment,如果查看Segmentput操作,我们会发现内部使用的同步机制是基于lock操作的,这样就可以对Map的一部分(Segment)进行上锁,这样影响的只是将要放入同一个Segment的元素的put操作保证同步的时候,锁住的不是整个MapHashTable就是这么做的),相对于HashTable提高了多线程环境下的性能,因此HashTable已经被淘汰了

在百度上搜索:concurrenthashmaphashtable区别,得到以下网址:https://blog.csdn.net/seu_calvin/article/details/52653711

 

 

 

总结多线程

1.       线程的生命周期:新建态、就绪态、运行态、阻塞态、死亡态

2.       创建线程的两种方式。

3.       线程安全:

a)         线程安全(线程同步):线程切换具有随机性,有时候线程正在执行一半就切换了,这样就不同步了。

b)         临界区资源:多个线程共享的资源(一段代码,数据),线程同步就是对临界区资源进行保护

c)         线程同步的原理:给临界区资源加锁。

4.       锁:

 

 

 

 

 

 

 

1.       请介绍一下多线程:

   两种

   线程锁

   线程池

   多线程的好处。

   http://ifeve.com/java-concurrency-thread-directory/这个网站很全面

   https://www.cnblogs.com/bsjl/p/7693029.html

2.       Jvm调优。Jvm机制和内存管理

3.       线程的参数传递参数: https://blog.csdn.net/saycheesenn/article/details/52956331

4.       hive转化mapreduce的流程:

5.       你在jvm调优的时候都调过哪些参数。

6.       一个数组有一个add方法,有一个get方法。让它在多线程情况下线程安全:

https://blog.csdn.net/whf584201314/article/details/78961688

 

 

 

 

面试:

1.       假如面试官问我线程的问题

1.1 我的回答思路:

第一步:介绍线程的生命周期,创建线程的两种方式,临界区资源加锁。

第二步:然后同过线程锁Synchronizedlock介绍hashtableConcurrentHashMap,这样就可以继续介绍hashmap等了。

第三步:通过线程安全可以介绍单例模式,有懒汉模式和饿汉模式。其中懒汉模式在多线程情况下存在线程安全问题。饿汉模式不存在线程安全问题。

1.2   具体内容如下:

   线程的生命周期:新建、就绪态、运行态、阻塞态、死亡

   创建线程的两种方式:继承Thread类。重写runnable接口,创建runnable对象的时候一般后面跟着参数,参数是Thread类的对象(这也是高并发的思想,即多个线程访问一个对象),因此一般情况下runnableThread会一起使用。

   临界区资源:线程同步主要是对临界区资源的保护

   线程同步的办法是加锁:Synchronized,它可以同步方法或者同步代码块。同步方法的锁是this对象,同步代码块的锁是任意对象,同步静态方法的锁是类的字节码对象。

   Synchronized的优缺点:锁的释放由虚拟机来完成(获取锁的线程执行完了该代码块,然后线程释放对锁的占有;线程执行发生异常,此时JVM会让线程自动释放锁),不用人工干预,不过此即是缺点也是优点,优点是不用担心会造成死锁,缺点1:缺点是由可能获取到锁的线程由于等待IO就会阻塞,阻塞之后其他线程会一直等待,性能不高。缺点2:在举个例子:多个线程同时进行读和写文件的时候会出现线程安全问题,但是如果多个线程只是读文件的话不会造成线程安全问题,此时使用Synchronized就不太好了。缺点3:加锁和解锁的过程由jvm虚拟机来完成,虽然我们可以理解在哪里,但是我们没有真正的看到。

   java中使用锁的两个基本工具是 synchronized LockSynchronizedjava关键字,lockjava中的接口。Synchronized是悲观锁(互斥锁),lock是乐观锁。

   lock锁:为了更清晰的表达在哪里加锁在哪里解锁,jdk1.5以后出现了lock。一般使用ReentrantLock实现类做为锁。并且在加锁和解锁处需要通过lock()unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

 

视频地址:http://video.eastday.com/a/161219140718452473398.html?qid=01359

 

   HashTable里使用的是synchronized关键字,这其实是对对象加锁,锁住的都是对象(map集合的整体)整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。ConcurrentHashMap引入了水桶(Segment),上面代码中的最后一行其实就可以理解为把一个大的Map拆分成N个小的HashTable,在put方法中,会根据hash(paramK.hashCode())来决定具体存放进哪个Segment,如果查看Segmentput操作,我们会发现内部使用的同步机制是基于lock操作的,这样就可以对Map的一部分(Segment)进行上锁,这样影响的只是将要放入同一个Segment的元素的put操作,保证同步的时候,锁住的不是整个MapHashTable就是这么做的),相对于HashTable提高了多线程环境下的性能,因此HashTable已经被淘汰了。(其中的"分段锁"的方案,相比HashTable的全表锁在性能上的提升非常之大)。

   ConcurrentHashMapHashTable都是线程安全的。

   Hashtable是线程安全的。而hashmap是线程非安全的,即在多线程情况下不安全。Hashmap底层是数组+链表,我们可以看成是hashset集合+ LinkedList集合。其中hashset集合底层是16个水桶,而LinkedList集合的底层是单项链表。关于hashsetLinkedList的介绍在文档的开头部分。

   单例模式中的线程安全问题(由线程引出单例):懒汉模式中存在线程安全问题,单例模式有两种,即:懒汉模式和饿汉模式。网上的视频网站如下:http://v.youku.com/v_show/id_XMzQ0MzE4NjU0OA==.html

   懒汉模式的步骤:第一步:构造方法私有化,避免外部创建该类的对象。第二步:声明一个私有的静态变量(只是声明了),也就是属性(假设是变量s,此时创建这个变量为private static jvm instance =null)。第三步:创建一个对外的公共的静态方法访问该变量,如果变量没有对象,就创建该对象(if(instance ===null){ instance =new jvm()})。由此可知:懒汉模式的意思是自己懒得自己创建对象,当外界调用我的方法的时候在创建这个静态变量。

 

   懒汉模式的详解:正是由于这个静态变量由外界创建,因此在多线程情况下他们的地址会不一样(如果是单线程情况下创建两个对象,这两个对象的地址是一样的)。因为现在创建了两个线程,这两个线程都要使用共同的资源,即静态方法中的静态变,但是在多项线程情况下可能第一个线程还没new好这个instance静态变量呢,第二个线程此时也来new这个对象了。这就是在线程中常见的线程安全问题了,解决办法就是加锁。因此我们需要对懒汉模式使用Synchronized锁把这个对外的方法锁住。

  

这种锁的方式效率不高,因为abcde几个线程过来的时候都要判断这个静态变量是否为空,都要进入锁。锁住的是class对象。

   经典的双重检查:这种方式是如果这个静态变量不为空就不用在进入这个有锁的if语句了。内层if语句的作用是创建这个静态变量,而外层这个if语句的作用的是为了:如果静态变量已经存在了,就不进入这个锁了,这样提高已经存在对象时候的访问效率。

 

   懒汉模式的缺点:懒汉模式的效率不高,因为有Synchronized锁,就会导致在创建对象的时候需要等待资源。

   饿汉模式的步骤:第一步:构造方法私有化。第二步:声明私有的静态变量,同时创建好该对象。第三步:对外提供访问属性的静态方法。此图中,在类加载的时候就会创建静态变量。

 

   优化:把静态变量放到内部类中,如myjvm3。在myjvm3类加载的时候,静态变量不会初始化,只有在执行jvmhollder内部类的时候才会初始化这个静态变量。

 

   由线程因此JVM。问:java程序运行的时候,需要启动JVM虚拟机,这是单线程启动的还是多线程启动的?答:从表面上看,main方法是程序的入口,main方法在一个线程中,这样看似jvm是单线程的。但是还有一个垃圾回收线程也会启动,否则很容易发生内存溢出。因此jvm最低也会启动两个线程。因此jvm启动的时候是多线程的。

   Jvm中什么是垃圾,以及垃圾回收的算法。

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自1601844782.iteye.com/blog/2419484