在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决。
Future顾名思意,有点像期货市场的“期权”,是“对未来的一种凭证”,例如当我们买了某个房地产开发商的期房,交钱之后,开发商会给我们一个凭证
(期权),这个凭证告诉我们等明年某个时候拿这个凭证就可以拿到我们所需要的房子,但是现在房子还没建好。市场上之所以有“期货”,也正由于有这种需求,
才有这种供给。
这种应用在GUI上用的比较多,在设计模式中一般称为“虚拟代理模式”。
例如:现在有个这样的需求,Client向Server提交一个Request(int count,char
c),希望获取一个由count个字符c构造出来的字符串。比如发送Request(10,'K'),那么反馈字符串“KKKKKKKKKK”,但是我们
假设这个生成字符串的过程很费时间。
于是,为了获取比较好的交互性,我们的Server收到请求后,先构造一个FutureData,并把这个所谓的“期权(未来凭证)”反馈给
Client;于此同时,通过另一个并发线程去构造一个真正的字符串RealData,并在构造完毕后,RealData给FutureData报告一个
消息,说数据(期房)已经准备好了,此时Client可以通过期权拿到期房,但是假如我们的Client比较着急,还没等房子假好的时,就想要房子,怎么
办呢?这个时候我们可以阻塞Client所在的线程,让Client等待,直到最后RealData通知FutureData说房子好了,才返回。
这里的要点:
(1)Server先给Client一个“期权”,同时开一个线程去干活建房子(未来的“现房”);
(2)当“现房”RealData准备好了的时候,如何告诉FutureData说已经准备好了。(本处采用“回调过程”(借用观察者模式,来实现回调))
(3)如果客户比较着急,现房还没准备好的时候,就要取房,怎么办? 本处采用“阻塞”。
Data(公共数据接口)
-
package
com.umpay.future;
-
-
public
interface
Data {
-
public
abstract
String getContent();
-
}
FutureData(期权)
-
package
com.umpay.future.extend;
-
-
import
java.util.Observable;
-
import
java.util.Observer;
-
-
import
com.umpay.future.Data;
-
-
public
class
FutureData2
implements
Data,Observer {
-
-
-
-
-
-
-
private
volatile
RealData2 realData2 =
null
;
-
-
-
-
public
boolean
isFinished() {
-
return
realData2 !=
null
;
-
}
-
-
-
-
-
-
public
String getContent() {
-
synchronized
(mutex) {
-
while
(!isFinished()) {
-
try
{
-
mutex.wait();
-
} catch
(InterruptedException e) {
-
e.printStackTrace();
-
}
-
}
-
return
realData2.getContent();
-
}
-
}
-
-
-
-
-
-
-
-
-
public
void
update(Observable realData, Object event) {
-
System.out.println("通知...."
+event);
-
if
(!(realData
instanceof
RealData2)) {
-
throw
new
IllegalArgumentException(
"主题的数据类型必须是RealData2"
);
-
}
-
if
(!(event
instanceof
String)) {
-
throw
new
IllegalArgumentException(
"事件的数据类型必须是String"
);
-
}
-
synchronized
(mutex) {
-
if
(isFinished()) {
-
mutex.notifyAll();
-
return
;
-
}
-
if
(
"Finished"
.equals(event)) {
-
realData2 = (RealData2)realData;
-
mutex.notifyAll();
-
}
-
}
-
}
-
-
private
Object mutex =
new
Object();
-
}
RealData(实际数据)
-
package
com.umpay.future.extend;
-
-
import
java.util.Observable;
-
-
import
com.umpay.future.Data;
-
-
public
class
RealData2
extends
Observable
implements
Data {
-
-
private
String content;
-
-
public
RealData2() {
-
-
}
-
-
public
void
createRealData2(
int
count,
char
c) {
-
System.out.println(" making RealData("
+ count +
", "
+ c
-
+ ") BEGIN"
);
-
char
[] buffer =
new
char
[count];
-
for
(
int
i =
0
; i < count; i++) {
-
buffer[i] = c;
-
try
{
-
Thread.sleep(100
);
-
} catch
(InterruptedException e) {
-
}
-
}
-
System.out.println(" making RealData("
+ count +
", "
+ c
-
+ ") END"
);
-
this
.content =
new
String(buffer);
-
-
-
setChanged();
-
notifyObservers("Finished"
);
-
}
-
-
-
public
String getContent() {
-
return
content;
-
}
-
}
服务端代码:
-
package
com.umpay.future.extend;
-
-
import
com.umpay.future.Data;
-
-
public
class
HostServer2 {
-
-
public
Data request(
final
int
count,
final
char
c) {
-
System.out.println(" request("
+ count +
", "
+ c +
") BEGIN"
);
-
-
-
final
FutureData2 future2 =
new
FutureData2();
-
-
-
new
Thread() {
-
public
void
run() {
-
RealData2 realdata2 = new
RealData2();
-
realdata2.addObserver(future2);
-
realdata2.createRealData2(count, c);
-
}
-
}.start();
-
-
System.out.println(" request("
+ count +
", "
+ c +
") END"
);
-
-
-
return
future2;
-
}
-
-
}
客户端代码:
-
package
com.umpay.future;
-
-
import
com.umpay.future.extend.HostServer2;
-
-
public
class
MainClient {
-
public
static
void
main(String[] args) {
-
-
testHostServer2();
-
}
-
-
static
void
testHostServer() {
-
System.out.println("main BEGIN"
);
-
HostServer hostServer = new
HostServer();
-
Data data1 = hostServer.request(10
,
'A'
);
-
Data data2 = hostServer.request(20
,
'B'
);
-
Data data3 = hostServer.request(30
,
'C'
);
-
-
System.out.println("main otherJob BEGIN"
);
-
-
-
-
-
System.out.println("main otherJob END"
);
-
-
System.out.println("data1 = "
+ data1.getContent());
-
System.out.println("data2 = "
+ data2.getContent());
-
System.out.println("data3 = "
+ data3.getContent());
-
System.out.println("main END"
);
-
-
}
-
-
static
void
testHostServer2() {
-
System.out.println("main BEGIN"
);
-
HostServer2 hostServer2 = new
HostServer2();
-
Data data1 = hostServer2.request(10
,
'A'
);
-
Data data2 = hostServer2.request(20
,
'B'
);
-
Data data3 = hostServer2.request(30
,
'C'
);
-
-
System.out.println("main otherJob BEGIN"
);
-
-
-
-
-
System.out.println("main otherJob END"
);
-
-
System.out.println("data1 = "
+ data1.getContent());
-
System.out.println("data2 = "
+ data2.getContent());
-
System.out.println("data3 = "
+ data3.getContent());
-
System.out.println("main END"
);
-
-
}
-
}
分享到:
相关推荐
1、std::async会自动创建线程去调用线程函数,相对于低层次的std::thread,使用起来非常方便; 2、std::async返回std::future对象,通过返回的std::future对象我们可以非常方便的获取到线程函数的返回结果; 3、std:...
│ 高并发编程第二阶段38讲、多线程Active Objects设计模式(接受异步消息的主动对象)-上.mp4 │ 高并发编程第二阶段39讲、多线程Active Objects设计模式(接受异步消息的主动对象)-中.mp4 │ 高并发编程第二阶段40...
│ 高并发编程第二阶段38讲、多线程Active Objects设计模式(接受异步消息的主动对象)-上.mp4 │ 高并发编程第二阶段39讲、多线程Active Objects设计模式(接受异步消息的主动对象)-中.mp4 │ 高并发编程第二阶段40...
Channel选择器工厂与轮询算法及注册底层实现 72_Netty线程模型深度解读与架构设计原则 73_Netty底层架构系统总结与应用实践 74_Netty对于异步读写操作的架构思想与观察者模式的重要应用 75_适配器模式与模板方法模式...
为了实现这个功能,我们使用了JavaFX的`ExecutorService`和`Future`类来异步地发送消息,并使用了一个独立的线程来监听用户输入的消息。 具体来说,在`ChatApplication`类的`start()`方法中,我们首先创建了一个...
本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...
20_通过Apache Thrift实现Java与Python的RPC调用 21_gRPC深入详解 22_gRPC实践 23_Gradle Wrapper在Gradle项目构建中的最佳实践 24_gRPC整合Gradle与代码生成 25_gRPC通信示例与JVM回调钩子 26_gRPC服务器流式调用...
第20讲:通过Apache Thrift实现Java与Python的RPC调用 第21讲:gRPC深入详解 第22讲:gRPC实践 第23讲:Gradle Wrapper在Gradle项目构建中的最佳实践 第24讲:gRPC整合Gradle与代码生成 第25讲:gRPC通信示例与...
Tornado 4.0 已经发布了很长一段时间了, 新版本广泛的应用了协程(Future)特性. 我们目前已经将 Tornado 升级到最新版本, 而且也大量的使用协程特性. 很长时间没有更新博客, 今天就简单介绍下 Tornado 协程实现原理, ...
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
13.2 异步Future 252 13.3 异步Callback 253 13.4 异步编排CompletableFuture 254 13.5 异步Web服务实现 257 13.6 请求缓存 259 13.7 请求合并 261 14 如何扩容 266 14.1 单体应用垂直扩容 267 14.2 单体应用水平扩...