1. Java多线程编程中,常用的多线程设计模式包括:Future模式、Master-Worker模式、Guarded Suspeionsion模式、不变模式和生产者-消费者模式等
2. Java多线程编程中Future模式的详解
http://blog.csdn.net/ghuil/article/details/41048017
3. Java多线程编程中Master-Worker模式的详解
http://blog.csdn.net/ghuil/article/details/41048005
4. 异步Callback???
《亿级流量网站架构核心技术-13.3》
5. 异步编排CompletableFuture???
《亿级流量网站架构核心技术-13.4》
6.异步/同步
首先澄清一个概念,异步,同步和oneway是三件事。异步,归根结底你还是需要关心结果的,但可能不是当时的时间点关心,可以用轮询或者回调等方式处理结果;同步是需要当时关心
的结果的;而oneway是发出去就不管死活的方式,这种对于某些完全对可靠性没有要求的场景还是适用的,但不是我们重点讨论的范畴。
回归来看,任何的RPC都是存在客户端异步与服务端异步的,而且是可以任意组合的:客户端同步对服务端异步,客户端异步对服务端异步,客户端同步对服务端同步,客户端异步对服务端同步。
对于客户端来说,同步与异步主要是拿到一个Result,还是Future(Listenable)的区别。实现方式可以是线程池,NIO或者其他事件机制,这里先不展开讲。
服务端异步可能稍微难理解一点,这个是需要RPC协议支持的。参考servlet 3.0规范,服务端可以吐一个future给客户端,并且在future done的时候通知客户端。
整个过程可以参考下面的代码:
客户端同步服务端异步。
Future<Result> future = request(server);//server立刻返回future
synchronized(future){
while(!future.isDone()){
future.wait();//server处理结束后会notify这个future,并修改isdone标志
}
}
return future.get();
客户端同步服务端同步。
Result result = request(server);
客户端异步服务端同步(这里用线程池的方式)。
Future<Result> future = executor.submit(new Callable(){public void call<Result>(){
result = request(server);
}})
return future;
客户端异步服务端异步。
Future<Result> future = request(server);//server立刻返回future
return future
上面说了这么多,其实是想让大家脱离两个误区:
- RPC只有客户端能做异步,服务端不能。
- 异步只能通过线程池。
那么,服务端使用异步最大的好处是什么呢?说到底,是解放了线程和I/O。试想服务端有一堆I/O等待处理,如果每个请求都需要同步响应,每条消息都需要结果立刻返回,那么就几乎没法做I/O合并
(当然接口可以设计成batch的,但可能batch发过来的仍然数量较少)。而如果用异步的方式返回给客户端future,就可以有机会进行I/O的合并,把几个批次发过来的消息一起落地(这种合并对于MySQL等允许batch insert的数据库效果尤其明显),并且彻底释放了线程。不至于说来多少请求开多少线程,能够支持的并发量直线提高。
来看第二个误区,返回future的方式不一定只有线程池。换句话说,可以在线程池里面进行同步操作,也可以进行异步操作,也可以不使用线程池使用异步操作(NIO、事件)。
回到消息队列的议题上,我们当然不希望消息的发送阻塞主流程(前面提到了,server端如果使用异步模型,则可能因消息合并带来一定程度上的消息延迟),所以可以先使用线程池提交一个发送请求,主流程继续往下走。
但是线程池中的请求关心结果吗?Of course,必须等待服务端消息成功落地,才算是消息发送成功。所以这里的模型,准确地说事客户端半同步半异步(使用线程池不阻塞主流程,但线程池中的任务需要等待server端的返回),server端是纯异步。客户端的线程池wait在server端吐回的future上,直到server端处理完毕,才解除阻塞继续进行。
总结一句,同步能够保证结果,异步能够保证效率,要合理的结合才能做到最好的效率。
=====================zxb总结============================
//参照《轻量级Java_EE企业应用实战(第3版)》
-------创建型-----------
1.单例模式:减少系统开销和便于对单个对象的状态跟踪;
https://blog.csdn.net/goodlixueyong/article/details/51935526 快速理解单例模式5中实现方式
2.简单工厂模式(又叫静态工厂):工厂直接生产被调用对象,即只有一个工厂负责生产各种产品,违反高内聚责任分配原则;
3.工厂模式:每个产品都有相应工厂,相比简单模式只有一个工厂;
4.抽象工厂模式:工厂生产工厂对象
注:高内聚责任分配原则即单一责任原则,软件设计讲究高内聚低耦合;
-------结构型-----------
1.代理模式:
(1)当需要创建一个开销很大的对象:创建大图片代理类Proxy,在show动作时才真正创建大图片和显示;
Hibernate默认启用延迟加载,在关联关系@ManyToOne/@OneToMany, 如果不采用代理模式,系统在加载A实体时,同时加载A实体所有关联实体,开销会很大;
(2)目标对象的功能还不足以满足需求:可创建一个代理对象,增强原对象,Java里借用Proxy和实现InvocationHandler的invoke方法;
Spring AOP机制,本质就是动态代理模式,实现service服务日志记录(structs拦截器实现登陆控制)
2.装饰者模式:典型案例是对输出结果进行加强
JAVA中运用:BufferOutputStream可以对FileOutputStream增加缓冲功能
3.门面模式:用于将一组复杂的类包装成一个简单的接口 --- 意义不大!!!
Hibernate中的运用:HibernateTemplate
4.享元模式:
享元模式是一组共享的对象集合,单例模式只有一个对象;
享元模式目的是为了节约空间提升性能,单例模式是出于共享状态的目的;
java中应用:线程池、数据库连接池等;
5.桥接模式:---- 意义不大!!!
由于实际需要,某个类具有两个或两个以上维度变化,继承无法实现,桥接模式做法是把变化部分抽象出来,使变化部分与主体分离开来,从而实现多维度的彻底分离;
ZXB:本质是把多个对象公共变化部分抽出来,作为对象的属性,从而支持对象和属性两个维度的随时变化;
J2EE中的应用:
-------行为型-----------
1. 命令模式:把处理行为作为参数传入,即处理对象传入;
Hibernate中的应用:
2.观察者模式:当主题对象状态改变时,通知所有观察者
常见应用:监听、主题/订阅模式下的JMS等
java中的实现方式:
3.策略模式:---意义不大!!!