在对Java进行大量搜索之后,我对以下问题感到非常困惑:
为什么我会选择多线程方法的异步方法?
Java futures应该是非阻塞的。 非阻止是什么意思?当从Future
- 即,get()
中提取信息的方法阻塞并且只是暂停整个线程直到方法完成处理时,为什么称它为非阻塞?也许是一种回调方法,在处理完成后敲响完成的教堂钟声?
如何使方法异步?方法签名是什么?
public List<T> databaseQuery(String Query, String[] args){
String preparedQuery = QueryBaker(Query, args);
List<int> listOfNumbers = DB_Exec(preparedQuery); // time taking task
return listOfNumbers;
}
这种虚构的方法将如何成为一种非阻塞方法?或者如果你想要,请提供一个简单的同步方法和它的异步方法版本。
答案 0 :(得分:2)
为什么我会选择多线程方法的异步方法?
异步方法允许您减少线程数。您可以发出异步调用,然后在完成后通知,而不是在阻塞调用中绑定线程。这使得线程可以在此期间进行其他处理。
编写异步代码可能更复杂,但好处是提高了性能和内存利用率。
Java期货应该是非阻塞的。非阻塞是什么意思?当从
Future
- 即,get()
中提取信息的方法阻塞并且只是暂停整个线程直到方法完成处理时,为什么称它为非阻塞?也许是一种回调方法,在处理完成后敲响完成的教堂钟声?
查看在Java 8中添加的CompletableFuture
。这是一个比Future
更有用的界面。首先,它允许您将各种回调和转换链接到未来。您可以设置将在未来完成后运行的代码。正如你猜测的那样,这比在get()
电话中阻止要好得多。
例如,给定异步读取和写入方法如下:
CompletableFuture<ByteBuffer> read();
CompletableFuture<Integer> write(ByteBuffer bytes);
您可以从文件中读取并写入如下的套接字:
file.read()
.thenCompose(bytes -> socket.write(bytes))
.thenAccept(count -> log.write("Wrote {} bytes to socket.", count)
.exceptionally(exception -> {
log.error("Input/output error.", exception);
return null;
});
如何使方法异步?方法签名是什么?
你会让它回归未来。
public CompletableFuture<List<T>> databaseQuery(String Query, String[] args);
然后该方法负责在其他线程中执行工作并避免阻塞当前线程。有时您会准备好工作线程。如果没有,您可以使用ForkJoinPool
,这使后台处理非常容易。
public CompletableFuture<List<T>> databaseQuery(String query, String[] args) {
CompletableFuture<List<T>> future = new CompletableFuture<>();
Executor executor = ForkJoinPool.commonPool();
executor.execute(() -> {
String preparedQuery = QueryBaker(Query, args);
List<T> list = DB_Exec(preparedQuery); // time taking task
future.complete(list);
});
}
答案 1 :(得分:1)
为什么我要在多线程方法上选择异步方法
对我来说,它们听起来像是一样的东西,除了异步声音,它会在后台使用一个线程。
Java期货应该是非阻塞的吗?
非阻塞操作通常使用Future,但是对象本身是阻塞的,但只有在你等待时才会阻塞。
非阻止是什么意思?
当前线程不会等待/阻止。
为什么在从Future&lt;中提取信息的方法时将其称为非阻塞? some-object&gt;即get()阻止
你称它为非阻塞。在后台启动操作是非阻塞的,但如果您需要结果,阻塞是获得此结果的最简单方法。
并将简单地暂停整个线程,直到方法完成处理?
正确,它会这样做。
也许一种回调方法在处理完成时敲响完成的教堂钟声?
您可以使用CompletedFuture,或者您可以在任务中添加您想要执行的任何操作。您只需要阻止必须在当前线程中完成的事情。
您需要返回一个Future,并在等待时执行其他操作,否则使用非阻塞操作没有意义,您也可以在当前线程中执行它,因为它更简单,更高效
您已经拥有同步版本,异步版本看起来像
public Future<List<T>> databaseQuery(String Query, String[] args) {
return executor.submit(() -> {
String preparedQuery = QueryBaker(Query, args);
List<int> listOfNumbers = DB_Exec(preparedQuery); // time taking task
return listOfNumbers;
});
}
答案 2 :(得分:1)
我不是多线程的大师,但我也会为了自己的缘故尝试回答这些问题
为什么我会在多线程方法中选择异步方法? (我的问题:我相信我读的太多了,现在我自己很困惑)`
多线程正在使用多线程,除此之外别无其他。一个有趣的概念是多线程不能以真正的并行方式工作,因此将每个线程分成小比特,以提供并行工作的错觉。
多线程有用的一个例子是实时多人游戏,其中每个线程对应于每个用户。用户A将使用线程A而用户B将使用线程B.每个线程可以跟踪每个用户的活动,并且可以在每个线程之间共享数据。
另一个例子是等待长时间的http调用。假设你正在设计一个移动应用程序,并且用户点击下载以获得5千兆字节的文件。如果您不使用多线程,则在http调用完成之前,用户将无法执行任何操作。
值得注意的是,作为开发人员,多线程只是设计代码的一种方式。它增加了复杂性,并且不必总是这样做。
现在进行异步与同步,阻止与非阻止
这些是我在http://doc.akka.io/docs/akka/2.4.2/general/terminology.html
中找到的一些定义异步与同步
如果调用者在方法返回值或抛出异常之前无法进行,则方法调用被视为同步。另一方面,异步调用允许调用者在有限数量的步骤之后前进,并且可以通过一些附加机制(它可能是注册的回调,Future或消息)来发信号通知方法的完成。 / p>
同步API可能会使用阻塞来实现同步,但这不是必需的。 CPU密集型任务可能会产生与阻塞类似的行为。通常,最好使用异步API,因为它们可以保证系统能够进步。演员本质上是异步的:演员可以在发送消息后继续进行,而无需等待实际的传递发生。
非阻止与阻止
如果一个线程的延迟可以无限期地延迟其他一些线程,我们会谈论阻塞。一个很好的例子是一个资源,它可以由一个使用互斥的线程专门使用。如果线程无限期地保留资源(例如,意外地运行无限循环),则等待资源的其他线程无法进行。相反,非阻塞意味着没有线程能够无限期地延迟其他线程。
非阻塞操作比阻塞操作更受欢迎,因为当系统包含阻塞操作时,系统的整体进度并不是很容易保证。
我发现异步vs同步更多地指的是呼叫的意图,而阻止与非阻止指的是呼叫的结果。但是,说通常异步与非阻塞相关并且同步与阻塞相关并不是错误的。
2 - ; Java期货应该是非阻塞的吗?非阻塞是什么意思?当从Future&lt;中提取信息的方法时,为什么称它为非阻塞? some-object&gt;即get()是阻塞的,只是暂停整个线程,直到方法完成处理?也许是一种回调方法,在处理完成后敲响完成的教堂钟声?
非阻塞不会阻塞调用该方法的线程。
在Java中引入了期货以表示通话结果,尽管它可能尚未完成。回到http文件示例,假设您调用类似以下的方法
Future<BigData> future = server.getBigFile(); // getBigFile would be an asynchronous method
System.out.println("This line prints immediately");
方法getBigFile
将立即返回并继续执行下一行代码。您稍后可以检索未来的内容(或通知内容已准备好)。图书馆/框架如Netty,AKKA,Play广泛使用Futures。
如何制作方法异步?方法签名是什么?
我想说这取决于你想做什么。
如果你想快速构建一些东西,你可以使用Futures,Actor模型等高级函数,使你能够在多线程环境中高效编程,而不会犯太多错误。
另一方面,如果你只是想学习,我会说最好从使用互斥,信号量等的低级多线程编程开始。
如果您只是使用我编写的任何关键字搜索java异步示例,那么Google中的代码示例很多。 如果您有任何其他问题,请与我们联系!