1、RPC远程调用

RPC(remote procedure call)-远程过程调用,采用客户端/服务器模式,请求程序就是一个客户端,服务提供程序就是一个服务器;首先客户端调用一个有进程参数的调用信息到服务进程,然后等待应答信息,在服务气短,进程保持睡眠状态直到调用信息到达为止,当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

2、Spring Cloud与dubbo的区别

(1)开发难易

dubbo全是jar包依赖,开发阶段难度极大;Springcloud比较自由,无法强力约束接口规范;

(2)后续改进:

dubbo的改进是通过dubbofilter,很多东西没有,需要自己继承,如监控,日志,限流,追踪;

Springcloud自己带了很多监控,限流措施,

(3)配套措施

Springcloud是一套全方面的解决方案,是往体系方面发展的方案;

dubbo是一套全方面的服务化方案,而dubbo仅仅是一个工具;

(4)技术层面

对比双方源码,dubbo技术能力高于Springcloud,而Springcloud就是一堆简单的组件拼装;

总结:dubbo类似于Springcloud的一个子集,dubbo功能和文档完善,在国内使用起来还是一个门槛,dubbo具有调度、发现、监控、治理等功能,支持相当丰富的服务治理能力,dubbo架构下,注册中心对等集群,并会缓存服务列表已被数据库失效时间继续提供发现功能,本身的服务发现结构有很强的可用性与健壮性,足够支持高访问量的网站;Springcloud由众多个子项目组成,如config、Netflix、consul,提供了搭建分布式系统及微服务常用的工具,如配置管理、发现服务、断路由、微代理、控制总线、一次性token、全局锁、选举、分布式会话、集群;满足了构建微服务的所有解决方案;

3、Spring框架的IOC和AOP

(1)spring 是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架;

(2)spring下IOC容器和DI(依赖注入Dependency injection)

IOC容器:具有依赖注入功能的容器,可以创建对象的容器,IOC容器负责实例化、定位、配置应用程序中的对象建立这些对象的依赖。通常new一个对象,控制权由程序员控制,控制反转指的是new实例工作不是由程序员来做,而是交给Spring容器来做,在Spring中的BeanFactory是IOC容器的实际代表者。

DI(依赖注入Dependency injection):在容器创建对象,处理对象的依赖关系;依赖注入Spring的注入方式:set注入、静态工厂注入、构造方法注入、基于注解注入(推荐使用,便捷少配置);

注解注入:

@Component :把对象加入IOC容器,对象引用名称是类名,第一个字母小写;

@Component(”name“) :把指定名称的对象加入IOC容器;

@Repository 主要用于标识加入容器的对象是一个持久层的组件(类);

@Service 主要标识加入容器的对象是一个业务逻辑层的组件;

@Controller 主要用于标识加入容器的对象是一个控制层的组件;

@Resource 注入属性(DI),会从容器中找对象注入到@Resource修饰的对象上;

@Autowired 注入属性(DI),会从容器中找对象注入到@AutoWired修饰的对象上;

(3)spring下面向切面编程(AOP)和事务管理配置

AOP就是切面编程,如业务1和业务2都需要一个共同的操作,与其往每个业务中添加同样的代码,不如写一遍代码,让两个业务共同使用这段代码,如在订单管理,商品管理,资金管理,库存管理等业务,都会需要类似日志记录,事务控制,权限控制,性能统计,异常处理以及事务处理;AOP把所有共有的代码全部抽取出来,放到某个地方集中管理,然后具体运行时,再由容器动态织入这些共有代码。

(4)AOP涉及名称:

切面(Aspect):共有功能的实现;是存放在共有功能的Java类,之所以被AOP容器识别成切面,是配置中指定的;

通知(Advice):是切面的具体实现,以目标方法为参照点,根据放置的地方不同,可分为前置通(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5种。在实际应用中通常是切面类中的一个方法,具体属于哪类通知,同样是在配置中指定的。

连接点(joinpoint):程序运行时能够插入切面的地点;

切入点(pointcut):通知应该切入到哪些连接点上;

目标对象(target):即将切入切面的对象,也就是那些被通知的对象。

代理对象(proxy):通知应用到目标对象之后被动态创建的对象;

织入(weaving):将切面应用到目标对象从而创建一个新的代理对象的过程;这个过程可以发生在编译期,装载期以及运行期,不同的发生点有不同的前提条件;

(5)AOP配置事务管理

三部分组成,分别是DataSource、TransactionManager、代理机制;无论哪种配置方式,一般变化的是代理机制;

4、多线程

(1)线程的五个阶段:创建-->就绪-->运行-->阻塞-->终止;

(2)多线程实现的两种手段:继承Thread类、实现runnable接口;

(3)Thread和runnable的区别

若继承Tread,则不适合资源共享,但是如果实现了Runable接口,很容易实现资源共享;

实现runnable接口比继承Thread类所具有的的优势:

1、适合多个相同程序代码的线程去处理同一资源;

2、可以避免Java中单继承的限制;

3、增加程序的健壮性、代码可以被多个线程共享,代码和数据独立;

4、线程池只能放入实现runnable或者callable类线程,不能直接放入继承Thread的类;

(4)注意

main方法也是一个线程,Java中的线程都是同时启动的,哪个先执行,看谁先得到CPU资源;在Java中,每次程序运行至少启动2个线程,一个是main线程,一个是垃圾收集线程。

(5)线程状态转换

 

1、新建状态(new):新创建了一个线程对象;

2、就绪状态(Runable):线程对象创建后,其他线程调用了该对象的start()方法,该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权;

3、运行状态(running):就绪状态的线程池获取了cpu,执行;

4、阻塞状态(blocked):阻塞状态是线程因为某种原因放弃了CPU的使用权,暂时停止运行,直到线程进入到就绪状态,才有机会转到运行状态。阻塞情况分为三种:

(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。(wait会释放持有的锁)

(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。

(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转到就绪状态。(sleep不会释放所有的锁)

5、死亡状态(dead):线程执行完了或者因为异常退出了run()方法,该线程结束生命周期;

(6)线程调度

1、线程睡眠:Thread.sleep(long millis)方法;使线程转到阻塞状态。millis参数设置睡眠时间,以毫秒为时间,当睡眠结束后,就转为就绪(runnable)状态;

2、线程等待:wait()方法,导致当前线程等待,直到其他线程调用对象的notify()方法或者notifyall()唤醒方法;

3、线程让步:Thread.yield方法,暂停当前正在执行的线程对象,把执行机会让给相同的或者优先级更高的线程;

4、线程加入:join()方法,当前线程调中,另外一个线程用join()方法,当前线程转到阻塞状态,直到另一个线程运行结束,此时当前线程由阻塞转入到就绪状态;

5、线程唤醒:notify()方法以及notifyAll()方法;

5、List、Set、Map的区别

(1)List(列表)

list的元素以线性方式存储,可以放重复的对象

list主要有以下2个实现类:

ArrayList:长度可变的数组,可以对元素进行随机访问,向ArrayList插入或者删除元素速度慢;

LinkList:采用链表数据结构,插入和删除速度快,但访问速度慢;

(2)Set(集合)

set中对象不按特定(HashCode)的方式排序,并且没有重复对象;

Set有以下两个实现类:

HashSet: HashSet按照哈希算法来存储集合中的对象,存储速度快;

TreeSet: TreeSet实现了SortedSet接口,能够对集合中的对象进行排序;

(3)Map(映射)

Map是一种把键对象和值对象映射的集合,它的每一个元素都包括一个键对象和值对象;

Map主要有以下2种实现类:

HashMap:基于散列表实现,底层整体结构是一个数组,数组中的每个元素优势一个链表,其插入和查询<K,V>的开销是固定的,可以通过构造器设置容器和负载因子来调整容器的性能;

TreeMap:基于红黑树实现,查看<K,V>时,他们会被排序;

6、Java的原子性

由Java内存模型来直接保证原子性变量操作包括red,load,use,assign,store和write六个,大致可以认为基本数据类型和读写是具备原子性,如果应用场景需要一个更多大量范围的原子性保证,Java内存还提供了lock和unlock操作来满足这些需求,尽管虚拟机没有吧lock和unlock操作直接开放给用户使用,但是提供了更加高层次的字码指令monitorenter和monitorexit来隐匿的使用这两个操作,这两个字节码指令反映到Java代码就是同步块--synchronized关键字,因此synchronized也是具备原子性的;

7、Java的原子性操作

原子性操作即为最小操作单元,比如i=1,就是一个原子性操作,这个过程只涉及到一个赋值操作,如果操作不符合原子性操作,那么整个语句执行就会出现混乱,导致出现错误的结果,从而导致线程安全,所以多线程需要保证线程安全问题,就必须保证原子性操作,那么如何保证原子性操作?第一,加锁,比如使用synchronized代码块保证线程的同步,从而保证线程的原子性,但是加锁会使开销比较大;第二,使用atomic来实现原子性操作;