目录
string,stringbuffer和stringbuilder有什么区别?
Concurrenthashmap的原理,jdk1.7版本和jdk1.8版本有什么区别?
重写和重载的区别?
重载:是发在一个类中,同名的方法有不同的参数列表(类型不同、个数不同、顺序不同),视为重载。重写:是发生在子类于父类之间,要求子类被重写的方法和父辈被要求重写的方法有返回相同的类型,比父类被重写后更好的访问,不能比父类被重写后声明更多的异常。
string,stringbuffer和stringbuilder有什么区别?
可变性:string类中的底层有final修饰符,是不可变的。stringbuffer和stringbuilder继承于AbstractStringBuilder 底层没有final修饰是可变的。
安全性:string对象是不可变的,可以将它视为常量,线程安全。
stringbuffer对方法进行了同步锁或者对调用的方法进行了同步锁,线程安全。
stringbuilder没有对方法进行同步锁,非线程安全。
性能::每次修改string类型的,就会生成一个新的string对象,指针指向新得string对象,
stringbuffer和stringbuilder对自己本身修改不会生成新的对象,stringbuilder要比stringbuffer的性能高,但是有多线程不安全的风险。
==于equals的区别?
对于基本类型和引用类型==的效果不同,基本类型比较的是值,引用类型比较的引用的是否相同
equals于==基本相同,只不过string、integer等重写了equals方法,把他比较的是值。
synchronized关键字的使用
修饰实例方法,作用于实例对象上的加锁,在同步代码块的时候获取当前对象的实例锁
修饰静态方法,作用于类对象上的加锁,在同步代码块的时候获取当前类对象的锁,
修饰代码块,给指定对象加锁,在同步代码库的时候获取给指定的对象的锁。
接口与抽象类有什么区别?
关键字不一样:抽象类的子类继承用extends 继承,接口用implements来实现接口。
构造函数:抽象类中可以有构造函数。接口不可以构造函数。
实现个数:一个类可以实现多个接口,只能继承一个抽象类。
修饰符:接口默认方法public修饰,抽象中的抽象方法可以使用public和Protected 修饰。
接口中除了static,final变量 ,不能有其他变量。抽象类则不一样。
设计模式:抽象是对类的抽象,是一种模板设计。接口是对行为的抽象,是一种行为规范。
collection和collections有什么区别
collection是一种集合接口,在提供了对像的基本操作的通用接口方法,所有集合都它的子类比如,list和set等。collections是一种并发包,它里边有很多静态方法,不能被实例化,他提供了排序法,比如collections.sort(list).
list、set、map有什么区别?
元素是否有序 | 元素是否重复 | ||
list | 有序 | 可重复 | |
set | AbstractSet | 无序 | 不可重复 |
hashSet | |||
TreeSet | 有序(二叉树排序) | ||
map | AbstractMap | 无序 | key是唯一 value可重复 |
hashMap | |||
TreeMap | 有序(二叉树排序) |
HashMap和HashTable有什么区别?
hashmap运行key和value为null,hashtable不允许。
线程安全:hashtable线程安全,hashmap非线程安全。
使用:hashtable是保留类不推荐使用,单线程推荐使用hashmap,多线程推荐使用Concurrenthahsmap替代
Hashmap的实现?
hashmap是基于hash,put(key,vaule)存储,get(key)取,当key传入时,hashmap会根据key.hashcoud()计算出hash值,然后根据hash值存储到bucket 里,当hash值相同的时候,我们称 它为hash冲突,会存储到链表或者红黑树,当hash冲突少使用链表否则使用红黑树。
HashSet的实现?
HashSet使基于HahsMap是实现的,hashset是调用底层hashmap来保存元素的。hashset不允许重复。
Concurrenthashmap的原理,jdk1.7版本和jdk1.8版本有什么区别?
jdk1.7
数据结构:ReentrantLock +segment+hashEntry 每个segment都有一个hashEntry数组,hashEntry都是链表结构。
元素查询:二次hash,第一次hash定位到segment,第二次hash定位到元素所在的链表头部
锁:segment分布锁,segment继承ReentrantLock ,锁定操作segment,其他segment不受其影响。并发力度segment由构造函数指定。数组扩容不受其影响segment,get无需加锁。
jdk1.8
数据结构:synchronized+Node+CAS+红黑树,Node的val和next都是由volatile 修饰保证。
查找、替换、赋值都是由CAS
锁:锁链表的haed节点,不受其他元素的读写,锁粒度细,效用更高,扩容时,堵塞所有读写操作,并发扩容。
读操作无锁:noed的val和next都由volatile 修饰,读写线程与该变量相互可见
数组用volatile 修饰,保证扩容时被读线程感知。
线程安全类有哪些集合类?
hashtable,vector ,stack 都是线程安全类,就像hashmap是非线程安全类,但是随着jdk1.5之后的java.util.concurrent 并发包出现,他们都有自己对应得线程安全类,就像hashmap对应的线程安全类concurrenthashmap。
创建线程有哪几种方式?
三种方式:继承Thread ,重写run方法。
实现Runnable 接口
实现Callable 接口
Runnable和Callable有什么区别?
Runnable没有返回值,Callable有返回值,可以把Callable看成Runnable的补充。
ArrayList和LinkedList的区别?
ArrayLIst是基于动态数组,连续内存存储,合适下标访问,扩容机制:固定数组长度,当数据长度超过固定数组,会创建新的数组,将老的数组拷贝到新的数组里边。如果没有使用尾部注入法会导致元素移动,使用尾部注入法的性能会大大提高,甚至会超过LinkedList。
LinkedList是基于链表,分部内存存储,适合删除数据,插入数据,不适合做查询,LinkedList查询必须使用iterator (迭代器),不能使用for循环,for循环本身的get(i)每次获取到一个元素值,就会遍历list一边,性能消耗极大。
线程有哪些状态?
新建线程对象进入新建状态——>调用start(t.start)进入就绪状态——>cpu获取时间片,进入运行状态——>调用sleep 或者wait进入堵塞状态,休眠结束后——>调用notify 或者notifyAll重新进入就绪状态,cpu重新获取时间片,运行状态,代码执行完或者代码异常退出run方法,线程生命周期结束,进入终结状态。
sleep()和wait()有什么区别?
类不同:sleep来自Tread ,wait来自object
锁:sleep不会释放锁,wait释放锁
用法不同:sleep自动唤醒,wait需要调用notify或者notifyAll唤醒
notify()和notifyAll()有什么区别?
notify唤醒一个线程,notifyAll唤醒全部线程,会移到锁池去抢锁,抢到锁的继续往下执行,没有抢到锁的等锁被释放接着抢锁。notify唤醒一个线程,具体哪个,有虚拟据说了算。
start和run方法有什么区别?
start用来开启线程,run在线程执行时调用,可重复调用
start之调用一次
说一说几种常见的线程池及适用的场景
固定线程池:适用于负载较重的服务器
单一线程池:适用于需要保证顺序的各个任务,并在任意时间点,没有多线程的场景
可变线程池:大小无界,使用于执行很多的短期异步任务的小程序,或者适用于负载较轻的场景
延迟线程池:
继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。使用DelayQueue作为任务队列。