Java多线程异步调度程序分析(二)
源自:http://blog.sina.com.cn/s/blog_4cc16fc50100c0uh.html
public abstract class Result { //抽象的结果类
public abstract Object getResultValue();
}
class FutureResult extends Result{ //取货凭证类
private Result result;
private boolean completed;
public synchronized void setResult(Result result){ //存放真实的结果
this.result = result;
this.completed = true;
this.notifyAll();
}
public synchronized Object getResultValue(){ //取结果
while(!this.completed){
try{
this.wait();
}catch(Throwable t){}
}
// 调用RealResult类的getResultValue返回真实结果
return this.result.getResultValue();
}
}
class RealResult extends Result{ //表示真实结果的抽象类
private final Object resultValue;
public RealResult(Object resultValue){
this.resultValue = resultValue;
}
public Object getResultValue(){
return this.resultValue;
}
}
现在这个异步消息处理器已经有了模型,这个异步处理器包括如下对象
Servant 忠心做真实的事务
ActivationQueue 将请求缓存起来以便调度
Scheduler 对容器中的请求根据一定原则进行调度执行
Proxy 将特定方法请求转换为特定对象
所有这些都是这个异步处理器的核心部件,既然是核心部件,我们就要进行封装而不能随便让调用者来修改,所以我们用工厂模式来产生处理器Axman对象
public class AxmanFactory {
public static Axman createAxman() {
Servant s = new Servant(); //创建实际处理请求的对象
ActivationQueue queue = new ActivationQueue(); //创建存放请求的队列
Scheduler st = new Scheduler(queue); //创建调度策略对象
Proxy p = new Proxy(st,s); //创建代理对象
st.start(); //启动调度策略线程Scheduler
return p; //返回代理对象
}
}
用两个请求的产生者不停产生请求
public class ResultInvokeThread extends Thread{
// ResultInvokeThread线程发送需要有返回值的请求
private final Axman ao;
private final char c;
public ResultInvokeThread(String name,Axman ao){
this.ao = ao;
this.c = name.charAt(0);
}
public void run(){
try{
int i = 0;
while(true){
//调用Proxy的ruseultTest方法向队列中添加一个请求,返回取货凭证FutureResult
Result result = this.ao.resultTest(i++,c);
Thread.sleep(10); //等待一段时间
String value = (String)result.getResultValue();
System.out.println(Thread.currentThread().getName() + " value = " + value);
}
}
catch(Throwable t){}
}
}
public class NoResultInvokeThread extends Thread{
//NoResultInvokeThread发送不需要返回值的请求
private final Axman ao;
public NoResultInvokeThread(String name,Axman ao){
super(name);
this.ao = ao;
}
public void run(){
try{
int i = 0;
while(true){
String s = Thread.currentThread().getName() + i++;
ao.noResultTest(s);
Thread.sleep(20);
}
}
catch(Throwable t){}
}
}
// 调用程序的主类
public class Program {
public static void main(String[] args) {
//创建代理对象,同时启动调度策略线程Scheduler。
Axman ao = AxmanFactory.createAxman();
new ResultInvokeThread("Axman",ao).start(); //启动需要返回值的请求线程
new ResultInvokeThread("Sager",ao).start();
new NoResultInvokeThread("Macke",ao).start();//启动不需要返回值的请求线程
}
}
1. Scheduler线程运行后,从队列ActivationQueue中取出请求,调用不同请求类型相应的execute方法。
如果请求类型为ResultRequest,ResultRequest的execute方法首先调用Servant的resultTest方法,处理请求(请求处理完成后,返回处理结果RealResult对象);然后调用FutureResult的setResult方法存储结果。
ResultRequest的execute方法
public void execute(){
//创建Result对象,获取的是RealResult对象。
Result result = servant.resultTest(this.count,this.c);
this.future.setResult(result); //将RealResult对象存储。
}
Servant的resultTest方法
public Result resultTest(int count,char c){
char[] buf = new char[count];
for(int i = 0;i < count;i++){
buf[i] = c;
try{
Thread.sleep(100);
}catch(Throwable t){}
}
//调用RealResult的构造方法,返回RealResult对象。
return new RealResult(new String(buf));
}
FutureResult的setResult方法
public synchronized void setResult(Result result){
this.result = result;
this.completed = true;
this.notifyAll();
}
2. ResultInvokeThread线程运行后,调用Proxy的ruseultTest方法。
resultTest方法创建取货凭证对象FutureResult,然后调用scheduler的invoke方法(invoke方法调用ActivationQueue队列的putRequest方法,向队列中添加请求。),然后返回取货凭证对象。
请求线程调用sleep()等待一段时间。
ResultInvokeThread线程继续调用Result的getResultValue对象,读取执行结果。
3. 程序中有两处需要同步
一是读取与存储请求,这涉及到ActivationQueue队列的getRequest方法和putRequest方法。
Scheduler线程、ResultInvokeThread线程、NoResultInvokeThread线程会同时对这些方法进行访问
二是读取与存储结果,这涉及到FutureResult的getResultValue方法与setResult方法。
Scheduler线程、ResultInvokeThread线程、NoResultInvokeThread线程会同时对这些方法进行访问。
每个请求对应一个请求结果,请求A获取的是请求结果A,不会得到请求结果B。
FutureResult的getResultValue方法声明如下
public synchronized Object getResultValue(){
while(!this.completed){
try{
this.wait();
}catch(Throwable t){}
}
Java多线程异步调度程序分析(二)的更多相关文章
- Java 多线程异步处理demo
java中实现多线程 1)继承Thread,重写里面的run方法 2)实现runnable接口通过源码发现:第一种方法说是继承Tread然后重写run方法,通过查看run方法的源码,发现run方法里面 ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Java 多线程基础(十二)生产者与消费者
Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...
- Java 多线程:锁(二)
Java 多线程:锁(二) 作者:Grey 原文地址: 博客园:Java 多线程:锁(二) CSDN:Java 多线程:锁(二) AtomicLong VS LongAddr VS Synchroni ...
- Java多线程基础知识(二)
一. Java线程具有6种状态 NEW 初始状态,线程被创建,但是还没有调用start方法. RUNNABLE 运行状态,java线程将操作系统中的就绪和运行两种状态笼统的称作进行中. BLOCKE ...
- Java多线程编程——进阶篇二
一.线程的交互 a.线程交互的基础知识 线程交互知识点需要从java.lang.Object的类的三个方法来学习: void notify() 唤醒在此对象监视器上等待的单个 ...
- 多线程系列之 java多线程的个人理解(二)
前言:上一篇多线程系列之 java多线程的个人理解(一) 讲到了线程.进程.多线程的基本概念,以及多线程在java中的基本实现方式,本篇主要接着上一篇继续讲述多线程在实际项目中的应用以及遇到的诸多问题 ...
- (转载)Java多线程的监控分析工具(VisualVM)
原文链接:http://blog.csdn.net/chendc201/article/details/22905511 在Java多线程程序运行时,多数情况下我们不知道到底发生了什么,只有出了错误的 ...
- Java多线程干货系列—(二)synchronized
原文地址:http://tengj.top/2016/05/03/threadsynchronized2/ <h1 id="前言"><a href="# ...
随机推荐
- 有两个数组a,b,大小都为n;通过交换a,b中的元素,使sum(a)-sum(b)最小。
今天在浏览网页的时候,发现了一个叫做 华为面试题(8分钟写出代码) 的链接,不确定真实性,纯属好奇,就点进去看看 这个可能是很老的题目吧,因为我看到这题目时,底下有好多评论了.提到XX排序,内存占用 ...
- LayoutInflater的获取与使用
在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...
- 在ubuntu12.0.4上搭建samba服务器以实现文件共享
在安装之前samba服务器之前,先进行以下配置和测试. <壹> 准备工作 一.NAT联网方式 (1)硬件连接 无需网线,无需路由器 (2)虚拟机选择NAT连接方式 (3)测试网络通不通 在 ...
- 关于OA中权限越级的问题
最近被人问了一个问题, 在OA中我, 经理出差了,下属需要用到 经理的权限,应该怎么处理. 这个问题比较简单,大神,请指点一下. 一开始 ,我就被搞懵了. 我的回答是: 经理出差之前赋给权限就可以了. ...
- Mac 配置java版本 ---- MySql数据库权限设置 --- openfire
java -version 显示java 版本 sudo su - root 切换身份 cd /usr/local/openfire 进入openfire目录 cd bin/ 进入 bin vim o ...
- JavaScript高级之闭包的概念及其应用
主要内容: 什么是闭包 闭包使用的一般模式 闭包都能做些什么 本文是我的JavaScript高级这个系列中的第二篇文章. 在这个系列中,我计划分析说明 一下JavaScript中的一些常用的而又神秘的 ...
- 教你在你的应用程序中扩展使用dynamic类型
教你在你的应用程序中扩展使用dynamic类型 相信大家在开发中经常会接触到mvc中的ViewBag,有心的同学会,发现这就是一个dynamic类型,查看源码一谈究竟,本文也是根据dynamic来扩展 ...
- nginx优化 突破十万并发(转)
一.一般来说nginx 配置文件中对优化比较有作用的为以下几项: 1. worker_processes 8; nginx 进程数,建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计 ...
- WebX配置文件、启动与响应流程
** 最近几天一直在看Spring的Ioc和AOP的源码介绍,还有Webx的使用.看Spring的源代码让人眼花缭乱,webx的配置文件也会让人感觉错综复杂无从下手.今天把之前看到的想到的webx相关 ...
- bzoj1597
首先不难想到排序,这种无规律的东西一般都要转化为有规律才好做 首先以x为第一关键字,y为第二关键字升序排序 拍完序我们发现,若存在两块土地i,j x[i]<=x[j],y[i]<=y[j] ...