Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.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 多线程最佳实践:约束任务newFixedThreadPool_Java_Multithreading_Concurrency_Threadpool - Fatal编程技术网

Java 多线程最佳实践:约束任务newFixedThreadPool

Java 多线程最佳实践:约束任务newFixedThreadPool,java,multithreading,concurrency,threadpool,Java,Multithreading,Concurrency,Threadpool,我想在一个包含+-42Mio条记录的数据库上运行很多任务。我希望以5000条记录/次的批量运行此操作(导致850个任务)。 我还想限制java开始为我执行此操作的线程数(16个),我使用当前代码来完成此任务: ExecutorService executorService = Executors.newFixedThreadPool(16); for (int j = 1; j < 900 + 1; j++) { int start = (j - 1) * 5000;

我想在一个包含+-42Mio条记录的数据库上运行很多任务。我希望以5000条记录/次的批量运行此操作(导致850个任务)。 我还想限制java开始为我执行此操作的线程数(16个),我使用当前代码来完成此任务:

 ExecutorService executorService = Executors.newFixedThreadPool(16);
 for (int j = 1; j < 900 + 1; j++) {
     int start = (j - 1) * 5000;
     int stop = (j) * 5000- 1;
     FetcherRunner runner = new FetcherRunner(routes, start, stop);
     executorService.submit(runner);

     Thread t = new Thread(runner);
     threadsList.add(t);
     t.start();
 }
ExecutorService ExecutorService=Executors.newFixedThreadPool(16);
对于(int j=1;j<900+1;j++){
int start=(j-1)*5000;
int stop=(j)*5000-1;
FetcherRunner runner=新的FetcherRunner(路由、开始、停止);
执行器服务。提交(运行器);
螺纹t=新螺纹(流道);
螺纹列表。添加(t);
t、 start();
}

这是正确的方法吗?特别是在我印象中,java只是启动了所有任务…(
FetcherRunner
实现了
runnable

使用ExecutorService的第一部分看起来不错:

...
FetcherRunner runner = new FetcherRunner(routes, start, stop);
executorService.submit(runner);
有线程的部分不应该在那里,我假设你有它只是为了展示你以前是如何拥有它的

更新: 是的,您不需要在
executorService.submit(runner)
之后使用代码,这将产生大量线程。如果您的目标是等待所有提交的任务在循环结束后完成,那么您可以在提交任务时获得对
未来
的引用,并等待
未来
,如下所示:

ExecutorService executorService = Executors.newFixedThreadPool(16);
List<Future<Result>> futures = ..;
 for (int j = 1; j < 900+ 1; j++) {
 int start = (j - 1) * 5000;
 int stop = (j) * 5000- 1;
 FetcherRunner runner = new FetcherRunner(routes, start, stop);
 futures.add(executorService.submit(runner));

}
for (Future<Result> future:futures){
    future.get(); //Do something with the results..
}
ExecutorService ExecutorService=Executors.newFixedThreadPool(16);
上市期货=。。;
对于(int j=1;j<900+1;j++){
int start=(j-1)*5000;
int stop=(j)*5000-1;
FetcherRunner runner=新的FetcherRunner(路由、开始、停止);
futures.add(executorService.submit(runner));
}
for(未来:未来){
future.get();//对结果执行一些操作。。
}
这是正确的工作方式吗

第一部分是正确的。但是您不应该创建和启动新的线程对象。提交Runnable时,ExecutorService将其置于队列中,然后在工作线程可用时运行它

。。。。我使用threadlist来检测所有线程何时完成,以便继续处理结果

如果你做了你目前正在做的事情,那么你将运行每个任务两次。更糟糕的是,大量手动创建的线程都将尝试并行运行

确保所有任务都已完成的一个简单方法是调用Executor服务。(如果您不打算再次使用executor服务,则有序关闭executor服务将产生相同的效果。)


另一种方法是为每个
FetcherRunner
的结果创建
未来的
,并在提交所有任务后尝试
获取结果。这样做的好处是,您可以在生成后续结果之前开始处理早期结果。(但是,如果您不需要…或无法…这样做,使用Futures将无法实现任何目标。)

更改代码:

    ExecutorService executorService = Executors.newFixedThreadPool(16);
    for (int j = 1; j < 900 + 1; j++) {
        int start = (j - 1) * 5000;
        int stop = (j) * 5000 - 1;
        FetcherRunner runner = new FetcherRunner(routes, start, stop);
        executorService.submit(runner);

    }
ExecutorService ExecutorService=Executors.newFixedThreadPool(16);
对于(int j=1;j<900+1;j++){
int start=(j-1)*5000;
int stop=(j)*5000-1;
FetcherRunner runner=新的FetcherRunner(路由、开始、停止);
执行器服务。提交(运行器);
}

您不需要在调用后提交零件。创建线程的代码将导致创建900个线程!天呐ExecutorService有16个线程池,您可以一次运行16个作业。所有16个线程都忙时提交的任何作业都将排队。从文档中:

创建一个线程池,该线程池重用固定数量的操作线程 分享 无限队列。在任何时候,最多N个线程将是活动的处理任务。 如果在所有线程都处于活动状态时提交其他任务,它们将在 排队等待线程可用。如果任何线程在运行期间由于故障而终止 在关闭前执行,如果需要执行,将替换一个新的 后续任务。池中的线程将一直存在,直到显式关闭


因此,不需要另一个线程。如果您需要在任务完成后得到通知,您可以将其调出。其他选项是缓存从submit返回的所有Future,在每个任务完成后,您可以检查是否所有Future都已完成。在所有的Future都完成之后,您可以分派另一个函数来运行。但它将在ExecutorService中的一个线程上运行。

最好的方法是使用countdownlatch,如下所示

    ExecutorService executorService = Executors.newFixedThreadPool(16);
  CountdownLatch latch = new CountdownLatch(900);
 FetcherRunner runner = new FetcherRunner(routes, start, stop, latch);
 latch.await();

在FetcherRunner中的finally block下使用
latch.countDown()await()
之后的代码。

我确实有……但我使用线程列表检测所有线程何时完成,以便继续处理结果。你是在建议我在.submit之后放弃一切吗?+当我在executor上运行900个任务时,如果我将maxThreads限制在10个会有问题吗。@好的,谢谢你的提示,我没有意识到我在复制线程!@比丘、尤在解释发生的事情时最清楚:)