在多线程交互的中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"
);
-
-
}
-
}
分享到:
相关推荐
在本实例中,我们将深入探讨如何使用Java实现多线程以实现异步调用,并理解其背后的机制。 首先,多线程允许一个程序同时执行多个任务。在Java中,我们可以通过继承`Thread`类或实现`Runnable`接口来创建线程。在这...
下面是一个使用Python的`concurrent.futures`模块实现多线程异步调用(并参递参数)的示例: ```python import concurrent.futures def long_running_task(param1, param2): # 这里是耗时操作 result = param1 +...
总结,Java中的异步调用通过多线程、Future、Callable、CompletableFuture、回调函数等机制实现,极大地提高了程序的并发性能和响应性。在实际开发中,结合Spring框架和消息队列,我们可以构建高效、可扩展的后端...
本篇将深入探讨如何在Java中实现异步调用,以及相关的核心概念和技术。 1. **线程与并发** 异步调用的基础是线程并发执行。Java提供了多线程支持,通过`Thread`类或者`Runnable`接口可以创建并启动新线程。当一个...
Java多线程实现异步调用是提高程序效率的关键技术之一。在Java中,通过创建新线程并让它们独立运行来实现异步调用,这样可以使得主线程不被长时间阻塞,从而提高程序的响应速度。以下将详细介绍如何在Java中实现这一...
Java 实现线程异步是程序设计中的一个重要概念,它涉及到多任务并行处理和非阻塞执行。在Java中,我们可以通过多种方式来实现线程的异步操作,以提高程序的执行效率和响应速度。 一、Java Thread 类 Java Thread 类...
在Java中,异步Future机制是实现多线程并行处理的重要工具,它提供了对任务结果的预定义,允许在任务实际完成前进行后续操作。本文将深入探讨Java多线程中的异步Future机制,包括其原理、实现方式以及实际应用。 ...
### Java-多线程异步请求统一响应结果 #### 多线程异步请求概念 在Java编程语言中,多线程异步请求是一种高级编程技术,它允许开发者通过创建多个独立运行的线程来同时处理不同的任务或请求。与同步请求相比,这种...
在实际项目中,可以利用各种编程语言(如JavaScript的Promise、async/await,Java的CompletableFuture,或者.NET的async/await)来实现异步调用。 异步调用对于优化性能和提升用户体验至关重要。例如,在网页加载中...
另外,java.util.concurrent包提供了高级并发工具,如BlockingQueue,它在生产者-消费者模式中非常有用,可以实现线程间的异步通信。 Java多线程的PPT和示例会详细讲解以上这些概念,并通过实例代码展示如何在实际...
5. **NIO(非阻塞I/O)**: Java的`HttpAsyncClient`依赖于Java NIO(非阻塞I/O)来实现异步操作。NIO允许单个线程处理多个连接,显著提高了系统资源的利用率。 6. **线程池**: `HttpAsyncClient`通常会使用线程池来...
同步机制是Java多线程中解决竞态条件的关键,主要包含`synchronized`关键字、`Lock`接口及其实现类、`wait()`和`notify()`等方法。`synchronized`可以保证同一时刻只有一个线程访问特定的代码块,防止数据的不一致。...
最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...
Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,极大地提升了软件的效率和并发性。这份“Java多线程的经典资料.rar”压缩包包含了一份名为“Java线程.pdf”的文档,很可能是关于Java多线程的详细...
在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。接下来,我们将深入探讨这两个方法以及相关的知识点。 1. 继承Thread类 当一个类继承了Thread类,它就自动成为一个线程类。你需要重写...
- **start()**:调用start()会启动一个新的线程,执行run()方法中的代码,实现多线程并发执行。 - **run()**:直接调用run()方法,代码将在线程调用该方法的上下文中执行,即同步执行,不产生新的线程。 4. **...
Java中可以通过以下三种方式实现多线程: 1. **继承Thread类**:通过继承`Thread`类来创建自定义线程类,并重写`run()`方法,在其中编写线程执行的代码。 2. **实现Runnable接口**:实现`Runnable`接口的`run()`...
在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。本资料"Java多线程编程核心技术.zip"深入探讨了这些核心技术,并提供了源码供学习者实践和理解。 1. **线程的创建与启动** - 继承Thread类...
3. `java.util.concurrent`包:提供了更高级的并发工具,如`BlockingQueue`用于线程间的生产者-消费者模式,`ExecutorService`用于线程池管理,以及`Future`和`Callable`接口用于异步计算。 在进行多线程编程时,...