使用InputStream的Java库的非阻塞IO

时间:2012-12-06 23:11:07

标签: java scala playframework-2.0 akka nonblocking

我正在阅读非阻塞I / O,因为我正在使用Akka和Play并且阻塞是一个坏主意,如果我可以在那个上下文中可以避免,但是我不能让它工作连同我的用例:

  1. 通过网络获取文件(此处存在使用nio的备选方案,但现在我正在使用URL.openStream)
  2. 使用BouncyCastle解密文件(PGP)(这里我只限于InputStream)
  3. 使用标准Java GZIP(仅限于InputStream)解压缩文件
  4. 读取文件中的每一行,这是一个基于位置的平面文件,并转换为一个Case Classes(这里我没有读取方法的限制,现在scalax.io.Resource)
  5. 坚持使用Slick / JDBC(不确定JDBC是否阻止)
  6. 它现在基本上一直使用InputStreams。但是,为了学习和提高我的理解,我正在研究是否可以使用非阻塞IO来实现这一点。

    我基本上喜欢通过管道传输文件,然后我应用上面的每一步,最后保持数据不受阻塞。

    如果需要代码我可以轻松提供,但我正在寻找一个通用级别的解决方案:当我依赖使用java.io的库时我该怎么办?

3 个答案:

答案 0 :(得分:2)

我希望这有助于你的一些观点:

1/2/3/4)Akka可以与使用java.io.InputStreamjava.io.OutputStream的图书馆合作。请参阅此页面,特别是此部分:http://doc.akka.io/docs/akka/snapshot/scala/io.html

  

ByteStringBuilder可以通过asOutputStream方法包装在java.io.OutputStream中。同样,ByteIterator可以通过asInputStream包装在java.io.InputStream中。使用这些,akka.io应用程序可以集成基于java.io流的遗留代码。

1)你说通过网络获取文件。我猜是通过HTTP吗?您可以查看异步HTTP库。那里有许多相当成熟的异步HTTP库。我喜欢在scala中使用Spray Client,因为它是在akka之上构建的,所以在akka环境中播放效果很好。它支持GZIP,但不支持PGP。

4)另一种选择:文件是否足够小以存储在内存中?如果是这样,你不必担心异步,因为你不会做任何IO。在等待IO时你不会阻塞,而是你会经常使用CPU,因为内存很快。

5)JDBC正在阻塞。使用SQL查询作为参数调用方法,返回类型是包含数据的结果集。该方法必须在执行IO时阻止才能返回此数据。

有一些Java async database drivers,但我看到的所有内容似乎都没有维护,所以我没有使用它们。

不要害怕。阅读akka文档的这一部分,了解如何在akka环境中处理阻塞库: http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management

答案 1 :(得分:1)

  

使用BouncyCastle解密文件(PGP)(这里我只限于InputStream)

由于您在此步骤中仅限于InputStream,因此您已回答了自己的问题。您可以使用NIO执行涉及网络的部分,但步骤(2)需要InputStream。您可以使用NIO将文件从网络假脱机到磁盘,然后使用流,然后进行解压缩和解密(CipherInputStream)...在理论上仍然阻塞但在实践中仍然是连续的。

答案 2 :(得分:1)

我知道这不是完全阻止IO的,但我认为你应该考虑用Playframework意义上的非阻塞地图组合Futures(或Promsies)。

def getFile(location: String): File = { //blocking code} 

def decrypt(file: File): File = ..

def unzip(file: File): PromiseFile = ..

def store(file: File): String = ..

def result(status: String): SimpleResult[Json] = ..

AsyncResult{ 
  Promise.pure(getFile("someloc")) map decrypt map unzip map store map result 
}