1.谈谈对线程安全的理解?如何实现线程安全?
线程安全是多线程编程时的计算机程序代码中的一个概念。通过合理的时间调度,避开共享资源的存取冲突。另外,在并行任务设计上可以通过适当的策略,保证任务与任务之间不存在共享资源,设计一个规则来保证一个客户的计算工作和数据访问只会被一个线程或一台工作机完成,而不是把一个客户的计算工作分配给多个线程去完成。
2.如何创建一个线程
- 继承Thread类
- 实现Runnable()接口
- 实现Callable接口
- 通过线程池启动多线程
3.线程池的分类
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
- newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
- newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
- newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
- newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
4.ArrayList和LinkedList的区别。他们是线程安全的吗?有哪些线程安全的List?
- ArrayList基于数组实现,而ListedList基于链表实现;
- 在进行随机访问时,ArrayList比LinkedList效率更高,因为LinkedList需要移动指针;
- 在进行插入删除操作时,LinkedList比ArrayList效率更高,因为ArrayList需要大量移动元素;
- 线程安全的List:Collections.synchronizedList、CopyOnWriteArrayList
5.什么是深克隆和浅克隆?如何实现深克隆?
- 浅克隆是指拷贝对象时仅仅拷贝对象本身,而不拷贝对象包含的引用指向的对象,在新的对象中修改引用类型的数据会影响原对象中的引用。
- 深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象,原对象和新对象之间完全没有影响。
实现深克隆的方法:
- 手动为引用属性赋值实现深克隆
- 重写clone()方法使用序列化方法实现深克隆
6.锁有哪几种?谈谈悲观锁和乐观锁
公平锁/非公平锁
可重入锁
- 独享锁/共享锁
- 互斥锁/读写锁
- 乐观锁/悲观锁
- 分段锁
- 偏向锁/轻量级锁/重量级锁
- 自旋锁
乐观锁: 每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。
悲观锁: 线程拿到资源时,就对资源上锁,并在提交后,才释放锁资源,其他线程才能使用资源。每次想要拿到数据就必须等待拿到锁,会浪费很多时间。
7.IO与NIO
- IO面向字节流,而NIO面向缓冲区
- IO的各种流是阻塞的,如果在一次读写数据调用时数据还没有准备好,或者目前不可写,那么读写操作就会被阻塞直到数据准备好或目标可写为止;NIO是非阻塞的,每一次数据读写调用都会立即返回,即使当前没有可用数据,调用仍然会立即返回并且不对缓冲区做任何操作。
8.ip地址的分类
9.http与https的区别
http(超文本传输协议)、https(安全套接字层超文本传输协议)
- https协议需要到ca申请证书;
- http信息是明文传输,https则是具有安全性的ssl加密传输协议;
- http和https使用的是完全不同的连接方式,http使用80端口,https使用443端口;
- http的连接很简单,是无状态的;https协议是由ssl+http协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
10.TCP与UDP的区别
UDP(用户数据报协议):
- 无连接
- 面向报文
- 没有拥塞控制
- UDP 提供了单播,多播,广播的功能:支持一对一,一对多,多对多,多对一的方式
- 提供不可靠交付
- 适用于实时应用(IP电话、视频会议、直播等)
TCP(传输控制协议):
- 面向连接(三次握手)
- 面向字节流
- 具有流量控制和拥塞控制
- 仅支持单播传输
- 可靠交付
- 提供全双工通信
- 适用于要求可靠传输的应用(文件传输等)
11.介绍一下Spring
Spring是一个轻量级框架,JavaBean工厂,是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
- AOP(Aspect Orient Programming):指面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。通常使用AspectJ的编译时增强实现AOP,AspectJ是静态代理的增强,所谓的静态代理就是AOP框架会在编译阶段生成AOP代理类,因此也称为编译时增强。
- IOC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IOC更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。IOC体现了好莱坞原则 - "Don’t call me, we will call you"。依赖注入的基本原则是应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由容器负责,查找资源的逻辑应该从应用组件的代码中抽取出来,交给容器来完成。DI是对IOC更准确的描述,即组件之间的依赖关系由容器在运行期决定,形象的来说,即由容器动态的将某种依赖关系注入到组件之中。
12.springmvc的工作流程
- 接受请求到达前端控制器(DispatcherServlet);
- 前端控制器调用处理器映射器(HandlerMapping):得到由哪个Controller来处理;
- 前端控制器调用处理器适配器(HandlerAdapter):执行Controller得到ModelAndView并返回给前端控制器;
- 前端控制器将ModelAndView交给视图解析器(ViewResolver)解析,并返回视图;
- 响应回用户。