Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.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
Java 使用固定数量的线程和允许异常处理多线程数据_Java_Multithreading - Fatal编程技术网

Java 使用固定数量的线程和允许异常处理多线程数据

Java 使用固定数量的线程和允许异常处理多线程数据,java,multithreading,Java,Multithreading,我正在用主线程逐行浏览大文本文件(5GB)。创建几个其他线程以同时格式化这些行 我已经使用Runnable类和Semaphore编写了一个解决方案,它控制运行的线程数量。不幸的是,Runnable不提供返回值或引发异常。如果在任何线程中抛出异常,我希望我的整个应用程序停止 我现在正试图使用可调用和未来,但内存不足 public class ProcessLine implements Callable<Boolean> { private final String inputLi

我正在用主线程逐行浏览大文本文件(5GB)。创建几个其他线程以同时格式化这些行

我已经使用
Runnable
类和
Semaphore
编写了一个解决方案,它控制运行的线程数量。不幸的是,
Runnable
不提供返回值或引发异常。如果在任何线程中抛出异常,我希望我的整个应用程序停止

我现在正试图使用
可调用
未来
,但内存不足

public class ProcessLine implements Callable<Boolean> {
  private final String inputLine;

  public ProcessLine(String inputLine) {
    this.inputLine = inputLine;
  }

  @Override
  public Boolean call() throws Exception {
    formatLine(inputLine); // huge method which can throw exceptions

    return true;
  }
}
这里的第一个问题是,所有
Future
对象都收集在
futures
列表中。毫不奇怪,当我每行有一个项目时,我的内存就用完了

第二个问题是:在处理文本文件的最后,我将使用
get()
方法检查所有
Future
项。我甚至没有注意到第一行是否抛出了异常


请帮助我找出解决方法。

您可以通过创建自定义
ThreadPoolExecutor
来限制挂起任务的数量,方法如下:

ExecutorService executor = new ThreadPoolExecutor(
        threads,
        threads,
        0L,
        TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>(WORK_QUEUE_SIZE));

因此,存储任务处理的所有结果(对每个任务使用
Future
)占用了太多内存,但您可以单独对这些结果进行进一步处理,而不需要完整的集合(对吧?)

您可以考虑将每个任务传递到另一个工作队列,以供另一线程池处理。如果第二个工作队列具有固定大小,则保证内存使用是有限的。这是管道和过滤器设计模式的变体。它有一个很好的特性,即如果第二阶段的处理太慢,最终第二个工作队列将被填满,导致第一个线程池的线程阻塞。然后,第二个线程池的线程可以使用更多的CPU时间。也就是说,它以最大化吞吐量的方式在线程池之间自动共享CPU时间

如果开始处理(当处理的行数等于第二个队列的大小时),则保证在有限时间内检查处理文件第一行的结果,该结果可用于满足您及时处理问题的要求


我已经将这种设计用于一个程序,该程序下载数据并将其写入文件,以防止程序保留太多等待处理的数据

我尝试了其他几种解决方案,但我认为我自己找到了最适合我的

public static final ThreadStatus threadStatus = new ThreadStatus();

public static class ThreadStatus {
 private Exception exception = null;

 public void setException(Exception exception) {
   if(exception == null) {
     return;
   }

   this.exception = exception;
 }

 public Exception getException() {
   return exception;
 }

 public boolean exceptionThrown() {
   return exception != null;
 }
}

然后在线程的
run()
方法中:

catch(Exception e) {
  Main.threadStatus.setException(e);
}
在循环中遍历所有行:

ProcessLine processLine = new ProcessLine(inputLine);

Future f = executor.submit(processLine);
futures.add(f);
if(Main.threadStatus.exceptionThrown()) {
  throw Main.threadStatus.getException();
}

感谢所有帮助我的人。

如果我的文本文件超过了
工作队列大小中允许的
整数.MAX\u值
,会发生什么?那么未来的问题呢?不,不,工作队列的大小决定了你在任何时间点可以拥有多少个待定的未来。如果愿意,可以将1放在那里。已针对第二个问题更新。如果我在
executor.submit()之后立即调用
.get()
,我会立即知道格式化线程是否引发异常。但是我的主线程必须等待格式线程中的计算完成。这会阻止线程同时运行,并使多线程变得毫无意义。对吗?我总是使用4个格式的线程,现在我的应用程序花费的时间是原来的4倍。那么,难道你不能让处理行处理终止逻辑吗?或者将结果放入另一个由结果处理器处理的队列中。
catch(Exception e) {
  Main.threadStatus.setException(e);
}
if(Main.threadStatus.exceptionThrown()) {
  throw Main.threadStatus.getException();
}