等待执行器中的所有线程完成?
我正在实现并行快速排序作为编程实践,完成后,我阅读了 Executors 上的 Java 教程页面,这听起来像是它们可以使我的代码更快。不幸的是,我依靠 join() 来确保程序在所有内容都排序完成之前不会继续。现在我正在使用:
public static void quicksort(double[] a, int left, int right) {
if (right <= left) return;
int i = partition(a, left, right);
// threads is an AtomicInteger I'm using to make sure I don't
// spawn a billion threads.
if(threads.get() < 5){
// ThreadSort's run method just calls quicksort()
Future leftThread = e.submit(new ThreadSort(a, left, i-1));
Future rightThread = e.submit(new ThreadSort(a, i+1, right));
threads.getAndAdd(2);
try {
leftThread.get();
rightThread.get();
}
catch (InterruptedException ex) {}
catch (ExecutionException ex) {}
}
else{
quicksort(a, left, i-1);
quicksort(a, i+1, right);
}
}
这似乎工作正常,但是如果我在调用非递归quicksort()方法后立即运行e.shutdown(),它会出现一堆RejectedExecutionExceptions,所以我认为这不起作用以及我想要的。
所以无论如何,我基本上试图获得与 leftThread.join() 相同的功能,但使用执行器,我的问题是:
这是等待所有线程完成的最佳方法吗?
编辑:好的,所以我弄清楚为什么在关闭执行器后出现一堆错误,这是因为我在循环中调用这个函数(以平衡运行时间)而不是创建一个新的执行器。
I'm implementing a parellel quicksort as programming practice, and after I finished, I read the Java tutorial page on Executors, which sound like they could make my code even faster. Unfortunately, I was relying on join()'s to make sure that the program doesn't continue until everything is sorted. Right now I'm using:
public static void quicksort(double[] a, int left, int right) {
if (right <= left) return;
int i = partition(a, left, right);
// threads is an AtomicInteger I'm using to make sure I don't
// spawn a billion threads.
if(threads.get() < 5){
// ThreadSort's run method just calls quicksort()
Future leftThread = e.submit(new ThreadSort(a, left, i-1));
Future rightThread = e.submit(new ThreadSort(a, i+1, right));
threads.getAndAdd(2);
try {
leftThread.get();
rightThread.get();
}
catch (InterruptedException ex) {}
catch (ExecutionException ex) {}
}
else{
quicksort(a, left, i-1);
quicksort(a, i+1, right);
}
}
This seems to work ok, but if I run e.shutdown() right after I call my non-recursive quicksort() method, it has a bunch of RejectedExecutionExceptions, so I assume this isn't working as well as I had wanted.
So anyway, I'm basically trying to get the same functionality as leftThread.join() but with an Executor, and my questions is:
Is this the best way to wait until all of the threads are done?
EDIT: Ok, so I figured out why I got a bunch of errors after shutting down my Executor, it was because I was calling this function in a loop (to even out run times) and not creating a new Executor.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您使用什么类型的执行器?
ThreadPoolExecutor
< /a>.awaitTermination()
将执行您所询问的操作(这实际上是批量连接操作)。总而言之,ThreadPoolExecutor 将允许您设置线程数量的限制等...(如果线程计数变高,可能比像您所做的那样递归更好,不确定)。
PS - 我怀疑执行器会让你的代码运行得更快,但它们可能会让你的代码更容易阅读和维护。使用线程池将使此类算法的速度更快,并且执行器可以轻松使用线程池。
What type of executor are you using?
ThreadPoolExecutor
.awaitTermination()
will do what you are asking about (it's effectively a bulk join operation).As a total aside, ThreadPoolExecutor will allow you to set limits on the # of threads, etc... (might be better than going recursive like what you are doing if the thread count goes high, not sure).
PS - I doubt that executors will make your code run any faster, but they may make your code easier to read and maintain. Using a Thread pool will make things faster for this sort of algorithm, and the Executor makes it easy to work with thread pools.
看一下
Executors.newFixedThreadPool
它允许您创建最多 n 个线程的池(摆脱“if”)和ExecutorService.shutdown
方法和ExecutorsService.awaitTermination
方法。Take a look at
Executors.newFixedThreadPool
which lets you create a pool of at most n threads (gets rid of your "if") and theExecutorService.shutdown
method and theExecutorsService.awaitTermination
method.您可以使用 CountDownLatch
You could use a CountDownLatch
这是不正确的。
执行器可以由任意数量的不同执行系统(包括池线程)“支持”。
您需要正确调用工厂类。
此外,您还需要决定处理作业提交到队列的速度快于消耗速度的情况的策略,因为由于线程执行的限制,您最初可能不会耗尽内存,但是如果您对数百万个作业进行排队,那么它们在等待执行时必须存储在某个地方。
This is not correct.
The executor can be 'backed' by any number of different execution systems including pooled threads.
You need to call the factory class correctly.
Furthermore you also need to decide on a policy for dealing with situations where jobs are submitted to the queue faster than they can be consumed, because you may not initially run out of memory due to limits on the thread execution, but if you queue millions of jobs, then they have to be stored some place whilst they wait for execution.