1. 常用的集合有哪些,谈谈对它们的理解?

image.png
image.png
Collection接口:单列集合,有两个子接口
1.List接口
有三个实现类
LinkedList:基于链表实现,每一个元素存储本身内存地址的同时还存储下一个元素的地址。链表增删快,查找慢;
ArrayList:基于数组;每次增删都要创建新的数组,但数组有索引。数组增删慢,查找快
Vector:基于数组,线程安全的,效率低
2.Set接口:
有两个实现类
HashSet:存储的元素无序,不可重复,底层是哈希表
LinkedHashSet:存储的元素有序,不可重复,底层是哈希表和链表的结合

Map接口:双列集合
有三个实现类(HashMap,HashTable,TreeMap)
HashMap:非线程安全,高效,支持null;
LinkedHashMap:是HashMap的一个子类,保存了记录的插入顺序
HashTable:线程安全,低效,不支持null;
TreeMap: 能够把它保存的记录根据键排序,默认是键值的升序排序

2. IO流

image.png
image.png
字节流和字符流的区别
1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。
2.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
一些特别的流类型
转换流,转换流只有字节流转换为字符流,因为字符流使用起来更方便,我们只会向更方便使用的方向转化。如:InputStreamReader与OutputStreamWriter。
缓冲流,有关键字Buffered,也是一种处理流,为其包装的流增加了缓存功能,提高了输入输出的效率,增加缓冲功能后需要使用flush()才能将缓冲区中内容写入到实际的物理节点。但是,在现在版本的Java中,只需记得关闭输出流(调用close()方法),就会自动执行输出流的flush()方法,可以保证将缓冲区中内容写入。
对象流,有关键字Object,主要用于将目标对象保存到磁盘中或允许在网络中直接传输对象时使用(对象序列化)。
推回输入流,有关键字PushBack,当程序调用推回输入流的unread()方法时,系统回把指定数组内容的内容推回到一个推回缓冲区中,在调用read()方法读入内容时,就先从推回缓冲区中读取,直到读完推回缓冲区中内容后才会从原输入流中读取。

3. 线程和进程的区别?

进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独立单位
线程:是进程的一个实体,是cpu调度和分派的基本单位,是比进程更小的可以独立运行的基本单位
特点:线程的划分尺度小于进程,这使多线程程序拥有高并发性
进程在运行时各自内存单元相互独立,线程之间内存共享,这使多线程编程可以拥有更好的性能和用户体验
注意:多线程编程对于其它程序是不友好的,占据大量cpu资源。

4. 启动一个线程是调用run()方法还是start()方法?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM 调度并执行,这并不意味着线程就会立即运行。
run()方法是线程启动后要进行回调(callback)的方法。

5. 编写多线程程序的几种实现方式(换个问法:创建多线程的方式)?

(1)通过继承Thread类
(2)通过实现Runnable接口(推荐使用,因为Java中是单继承,一个类只有一个父类,若继承了Thread类,就无法在继承其它类,显然实现Runnable接口更为灵活)
(3)通过实现Callable接口(Java 5之后)

6.解决多线程安全问题的几种方式?

(1)同步代码块:
在代码块声明上 加上synchronized
synchronized (锁对象) {
可能会产生线程安全问题的代码
}
同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全。
(2)同步方法:
在方法声明上加上synchronized
public synchronized void method(){
可能会产生线程安全问题的代码
}
同步方法中的锁对象是 this
静态同步方法: 在方法声明上加上static synchronized
静态同步方法中的锁对象是 类名.class
(3)同步锁
Lock接口提供了与synchronized关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。

7.sleep()和wait()有什么区别?

1、每个对象都有一个锁来控制同步访问,Synchronized关键字可以和对象的锁交互,来实现同步方法或同步块。
sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!!!);
wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);
2、sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用;
3、sleep()是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,再次获得对象锁才会进入运行状态;

8.线程的五种状态和转换方式?

线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。
image.png

9. 什么是死锁?

  1. 两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程 都陷入了无限的等待中。

10.java虚拟机的运行机制?

image.png
详细请见:
http://www.cnblogs.com/zhanglei93/p/6590609.html

11.简述下你了解的设计模式?

(1)** 设计模式的分类(加粗为常用)**

设计模式的六大原则
· 开闭原则(Open Closed Principle,OCP)
· 里氏代换原则(Liskov Substitution Principle,LSP)
· 依赖倒转原则(Dependency Inversion Principle,DIP)
· 接口隔离原则(Interface Segregation Principle,ISP)
· 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
· 最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

(2) 单例模式

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
线程安全的饿汉式
image.png

(3) 工厂模式

  1. **意图:**定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。<br />** 主要解决:**主要解决接口选择的问题。<br />** 何时使用:**我们明确地计划不同条件下创建不同实例时。<br />** 如何解决:**让其子类实现工厂接口,返回的也是一个抽象的产品。<br />** 关键代码:**创建过程在其子类执行。<br />**工厂模式具体详见链接:**<br />http://blog.csdn.net/jason0539/article/details/23020989

(4) 装饰者模式

意图:装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用: 在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。。
关键代码:1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
装饰者模式具体详见链接:
http://www.runoob.com/design-pattern/decorator-pattern.html