Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与RxJava并行处理IO密集型任务列表_Java_Asynchronous_Reactive Programming_Observable_Rx Java - Fatal编程技术网

与RxJava并行处理IO密集型任务列表

与RxJava并行处理IO密集型任务列表,java,asynchronous,reactive-programming,observable,rx-java,Java,Asynchronous,Reactive Programming,Observable,Rx Java,我需要同时得到一些文件。get操作本身是IO密集型的,并且可以从并行执行中受益匪浅 使用RxJava,我可以通过使用Async.toAsync包装函数来实现这一点 我想知道是否有更干净的使用方法,或者?我没能弄明白。尝试了不同的方法,但任何方法都只能使用一个线程,并且处理是按顺序进行的 导入接收。可观察; 导入rx.Scheduler; 导入rx.functions.Func1; 导入rx.schedulers.schedulers; 导入rx.util.async.async; 导入java.

我需要同时得到一些文件。get操作本身是IO密集型的,并且可以从并行执行中受益匪浅

使用RxJava,我可以通过使用
Async.toAsync
包装函数来实现这一点

我想知道是否有更干净的使用方法,或者?我没能弄明白。尝试了不同的方法,但任何方法都只能使用一个线程,并且处理是按顺序进行的

导入接收。可观察;
导入rx.Scheduler;
导入rx.functions.Func1;
导入rx.schedulers.schedulers;
导入rx.util.async.async;
导入java.util.List;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
导入java.util.concurrent.TimeUnit;
公共类并行多重获取{
公共列表读取内容(列表路径){
Func1 getFunction=newfunc1(){
@凌驾
公共字符串调用(字符串路径){
返回get(路径);
}
};
Scheduler Scheduler=Schedulers.from(
Executors.newFixedThreadPool(
Math.min(path.size(),50));
未来结果=可观察
.从(路径)
.平面图(
toAsync(getFunction,scheduler))
托利斯先生()
.toBlocking()
.toFuture();
试一试{
返回result.get(30,TimeUnit.MINUTES);
}捕获(例外e){
//例如,如果上面的Func1.call抛出一个异常,它将在这里结束
抛出新的非法状态异常(“无法读取路径”,e);
}
}
私有字符串获取(字符串路径){
//这将是一个缓慢的操作,等待IO
返回“内容”;
}
}
即使这样也已经很不错了,因为我不需要构建自己的循环来提交未来并将它们的值组合到结果列表中。但也许不必如此冗长?

要想不那么冗长:

  • 您可以使用RxJava中的超时运算符
  • 您可以将java8与lambda一起使用,而不是Func1(但在您的情况下没有多大帮助)
  • 您可以避免创建自己的执行者
我得到的代码应该和你的代码一样:

  public List<String> readContents(List<String> paths) {

      try {

        return Observable
                .from(paths)
                .flatMap(Async.toAsync((Func1<String, String>) this::get, Schedulers.io()))
                .toList()
                .timeout(30, TimeUnit.MINUTES)
                .toBlocking().single();
      } catch (RuntimeException ex) { // the cause will be a timeoutException
        // For example if Func1.call above throws an exception it ends up in here
        throw new IllegalStateException("Couldn't read paths", ex);
      }
    }

    private String get(String path) {
        // this would be the slow operation, waiting for IO
        return "content";
   }
公共列表读取内容(列表路径){
试一试{
可观测回波
.从(路径)
.flatMap(Async.toAsync((Func1)this::get,Schedulers.io())
托利斯先生()
.超时(30,时间单位.分钟)
.toBlocking().single();
}catch(RuntimeException ex){//原因将是timeoutException
//例如,如果上面的Func1.call抛出一个异常,它将在这里结束
抛出新的IllegalStateException(“无法读取路径”,ex);
}
}
私有字符串获取(字符串路径){
//这将是一个缓慢的操作,等待IO
返回“内容”;
}

这不需要异步;仅仅是一个普通的
ExecutorService
就有了
.invokeAll()
,这确实值得一提。结果是一个列表,因此仍然需要至少迭代该列表并将值映射到列表中。使用
invokeAll()
,总体复杂度较低,但这个问题主要是关于如何使用RxJava实现这一点。如果能够找到一种方便的方法链接,并且能够使用
Observable.from
等,而不是“手动”迭代
路径来创建
invokeAll()
的任务,那就太好了。谢谢,就快到了
Async.toAsync
对我来说仍然有点笨拙,但如果RxJava就是这样做的,那就好了。
Schedulers.io()
的问题是它会创建无限多的线程。另一方面,
Schedulers.computation()
限制为4个线程(或者这可能取决于内核的数量)。这真的是另一个问题,扩展
调度程序
使其具有类似
调度程序的功能将非常简单。固定(int-size)
或更好的
调度程序。缓存(int-maxSize)
.timeout()
+
。single()
非常漂亮。感谢您的提示。您可以使用重载的flatMap(),它将并发订阅的最大观察数作为第二个参数。