我要推出很多任务要的+ -42Mio记录的数据库上运行。 我想5000的记录/次(结果850个任务)批次运行此。 我还希望限制线程数(16个)的Java开始为我做到这一点,我使用的是当前的代码来完成这个任务:
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();
}
这是做到这一点的正确方法是什么? 特别是我有一个Java的只是激发了所有任务的印象...( FetcherRunner
实现runnable
)
使用ExecutorService的第一部分看起来不错:
...
FetcherRunner runner = new FetcherRunner(routes, start, stop);
executorService.submit(runner);
与螺纹部分不应该在那里,我假设你有它存在只是为了告诉你如何收到了吗?
更新:是的,你不需要后的代码executorService.submit(runner)
,就是要结束了产卵的线程数量巨大。 如果你的目标是要等待所有提交的任务的循环后完成,那么你就可以得到一个参考Future
提交任务时,等待在Future
,这样的事情:
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..
}
这是工作的正确方法是什么?
第一部分是正确的。 但你不应该创建并启动新的Thread对象。 当您提交了Runnable的ExecutorService的把它放在它的队列,然后运行它,当一个工作线程变为可用。
....我用的对答时完成我所有的线程,所以我可以继续处理结果来检测。
那么,如果你这样做,你现在在做什么,你在两次运行的每个任务。 更糟糕的是,手动创建的线程群都将尝试以并行方式运行。
一个简单的方法,以确保所有的任务都已完成,是调用awaitTermination(...)
的ExecutorService的。 (执行者服务的一个有序的关闭将有同样的效果......如果你不打算再次使用。)
另一种方法是创建一个Future
每个FetcherRunner
的结果,并试图get
所有的任务已经提交后的结果。 这已被生产后来者之前,你可以开始处理结果早的优势。 (不过,如果你不需要......或者不能......做到这一点,利用期货起不到任何东西。)
你并不需要的部分,来电后提交。 你的代码创建一个线程会导致创建900个线程! Yowza。 该ExecutorService中有16个线程的线程池,你可以同时运行16个作业。 当所有16个线程都在忙着将排队提交的任何作业。 从文档:
创建一个可重用不受限制的队列操作螺纹固定数量的线程池。 在任何时候,顶多来确定nthreads线程将被激活的处理任务。 如果当所有线程是活动的其他任务提交,他们将在队列中等待,直到一个线程可用。 如果任何线程关闭前的执行过程中,由于终止与失败,如果需要执行后续任务的新一个将取而代之。 在池中的线程将一直存在,直到它明确地关闭。
因此,有没有需要另一个线程。 如果你需要一个任务完成后得到通知,你可以把它召唤出来。 其他选项是缓存所有的未来的从提交返回,并且一旦完成每一项任务,你可以检查,看看是否所有的Future的完成。 毕竟未来的完成,你可以派遣其他功能来运行。 但它会运行在ExecutorService的一个线程。
从您的代码更改:
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);
}
最好的办法是使用countdownlatch如下
ExecutorService executorService = Executors.newFixedThreadPool(16);
CountdownLatch latch = new CountdownLatch(900);
FetcherRunner runner = new FetcherRunner(routes, start, stop, latch);
latch.await();
在FetcherRunner下最后块使用latch.countDown();
后代码await()
将当所有任务都完成只执行。