我正在实现一个parellel quicksort作为编程实践,在我完成后,我阅读了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()相同的功能但是使用Executor,我的问题是:
这是等待所有线程完成的最佳方法吗?
编辑:好的,所以我弄清楚为什么在关闭我的Executor后出现了一堆错误,这是因为我在循环中调用了这个函数(甚至运行时间)并且没有创建新的Executor。
答案 0 :(得分:9)
您使用的是哪种执行者?
ThreadPoolExecutor
.awaitTermination()
会按照您的要求进行操作(实际上是批量加入操作)。
总而言之,ThreadPoolExecutor允许你设置线程数等的限制......(如果线程数很高,可能比你正在做的递归更好,不确定)。
PS - 我怀疑执行程序会使代码运行得更快,但它们可能会使代码更易于阅读和维护。使用线程池可以使这种算法更快,而Executor可以很容易地使用线程池。
答案 1 :(得分:4)
查看Executors.newFixedThreadPool
,它允许您创建最多n个线程的池(删除“if”)和ExecutorService.shutdown
方法以及ExecutorsService.awaitTermination
方法。< / p>
答案 2 :(得分:2)
您可以使用CountDownLatch
答案 3 :(得分:1)
PS - 我怀疑执行程序会让你的代码运行得更快,但是 它们可以使您的代码更易于阅读和维护。使用线程 池将使这种算法的速度更快,而且 Executor可以轻松使用线程池。
这不正确。
执行程序可以由任意数量的不同执行系统“支持”,包括池化线程。
您需要正确调用工厂类。
此外,您还需要确定一个策略来处理将作业提交到队列的速度超过可以消耗的情况,因为由于限制,您可能不最初耗尽内存线程执行,但如果你排队数百万个工作,那么他们必须在等待执行时存储在某个地方。