导读三个领域的中间件:远程过程调用和对象访问中间件:主要解决分布式环境下应用的互相访问问题。是支撑应用服务化的基础消息中间件:解决应用之间的消息传递、解耦、异步的问题数据访问中间件:解决应用访问数据库的共

三个领域的中间件:

  • 远程过程调用和对象访问中间件:主要解决分布式环境下应用的互相访问问题。是支撑应用服务化的基础

  • 消息中间件:解决应用之间的消息传递、解耦、异步的问题

  • 数据访问中间件:解决应用访问数据库的共性问题

构建Java中间件的基础知识

JVM中堆分为三块:Young/Tenured/Perm,新生代/年老代/持久代

一般来说,新对象分配在新生代的Eden区,也可能直接分配在年老代,在进行新生代垃圾回收时,Eden区存活的对象被复制到空的Survivor区,在下次新生代回收时,Eden区存活的对象和这个Survivor存活的对象被复制到另外那个Survivor区,并且清空当前Survivor区,经过多次新生代垃圾回收,还存活的对象会被移动到年老代。

线程池

1

2

3

4

ThreadPoolExecutor tp = new ThreadPoolExecutor(1, 1, 60, TimeUnit, SECONDS, new linkedBlockingQueue<Runnable>(count));

tp.execute(new Runnable(){

public void run(){}

});

使用线程池的方式是复用线程的,不用每次都创建线程。而创建线程的开销占比较大。

synchronized

synchronized修饰静态方法、对象方法、代码块

ReetrantLock

  • **提供tryLock方法,尝试调用,如果锁被其他线程持有,则tryLock立即返回

  • 可以实现公平锁

  • ReentrantReadWriteLock:读写锁,用于读多写少并且读不需要互斥的场景

  • 可以有多个Condition

volatile

可见性指一个线程修改变量值后,其他线程中能够看到这个值。volatile虽然解决了可见性问题,但是不能控制并发

Atomics

原子操作,如AtomicInteger内部通过JNI的方式使用了硬件支持的CAS指令

wait、notify和notifyAll

wait是等待线程,notify是唤醒一个等待线程(并不能指定,随机),notifyAll是唤醒所有的等待线程。

CountDownLatch

java.util.concurrent包中的一个类,主要提供的机制是当多个线程都到达了预期状态或完成预期工作时触发事件,其他线程可以等待这个事件来触发自己后续的工作。

CyclicBarrier

循环屏障,可以协同多个线程,让多个线程在这个屏障前等待,知道所有线程都到达了这个屏障时,再一起继续执行后面的动作。

Semaphore

Semaphore是用于管理信号量的,构造时传入可供管理的信号量的数值。如果信号量只有一个,就退化到互斥锁了,如果多于一个,则主要用于控制并发数。

Exchanger

用于两个线程之间进行数据交换,线程会阻塞在exchange方法上,知道另外一个线程也到了同一个Exchanger的exchange方法时,二者进行交换。

Future和FutureTask

Future是一个接口,FutureTask是一个具体实现类

1

2

3

4

5

6

7

8

9

10

11

Future<HashMap> future = getDataFromRemote2();

......

HashMap data = (HashMap) future.get();

public Future<HashMap> getDataFromRemote2(){

return threadPool.submit(new Callable<HashMap>(){

public HashMap call()throws Exception{

return getDataFromRemote();

}

});

}

getDataFromRemote2还是使用率getDataFromRemote完成操作,并且用到了线程池:把任务加入线程池中,把Future对象返回出去。

并发容器

  • CopyOnWrite:更改容器时,把容器复制一份进行修改,用于读多写少

  • Concurrent:尽量保证读不加锁,并且修改时不影响读,所以比读写锁更高的并发性能

动态代理

继承InvocationHandler

反射

Java反射机制是指在运行状态,对于任意一个类,都能知道这个类所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

1

2

3

4

5

6

7

8

9

10

11

12

Class clazz = Object.getClass();

String className = clazz.getName();

Method[] methods = clazz.getDeclaredMethods();

Field[] fields = clazz.getDeclaredFields();

// 构建对象

Class.forName("ClassName").newInstance();

// 动态执行方法

Method method = clazz.getDeclaredMethod("add", int.class, int.class);

method.invoke(this, 1, 1);

// 动态操作方法

Field field = clazz.getDeclaredField("name");

field.set(this, "test");

网络通信的选择

BIO、NIO、AIO

第三方框架,MINA,Netty

第四章 服务框架

服务调用端的设计与实现

调用发起==>寻址路由==>协议适配和序列化==>网络传输

==>反序列化 协议解析==>得到结果返回给调用方

1、确定服务框架的使用方式

2、服务调用者与服务提供者之间通信方式的选择

3、引入基于接口、方法、参数的路由

4、多机房场景,避免跨机房调用,一是在服务注册中心甄别,二是地址过滤

5、服务调用端的流控处理

6、序列化与反序列化处理,Java本身的序列化性能问题、跨语言问题、序列化后语言长度等

7、网络通信实现选择:BIO、NIO、AIO

8、支持多种异步服务调用方式:Oneway,Callback,Future,可靠异步

服务提供端的设计与实现

1、如何暴露远程服务

2、服务端对请求处理的流程

3、执行不同服务的线程池隔离

4、服务提供端的流控处理