线程池无法创建本机线程



我正在尝试以各种方式实现mergesort。我确实用fork/join实现了它,现在我想用ExecutorServiceThreadpool实现它。

我目前的工作是:

public class Test<T> implements Comparable<T> {
private final ThreadPoolExecutor executor;
public Test() {
//having this kind of threadpool prevent the program from generating any output whatsoever.
//executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
}

private void divide(LinkedList<T> dataToBeSorted) {
if (dataToBeSorted.size() < 2) {
return;
}
int mid = dataToBeSorted.size() / 2;
LinkedList<T> left = new LinkedList<>(dataToBeSorted.subList(0, mid));
LinkedList<T> right = new LinkedList<>(dataToBeSorted.subList(mid, dataToBeSorted.size()));
Future<?> f1= (executor.submit(() -> divide(left)));
Future<?> f2= (executor.submit(() -> divide(right)));
try {
f1.get();
f2.get();
} catch (InterruptedException | ExecutionException e) {
System.out.println("something went wrong went to sequential merge sort!");
new SeqMergeSorter<T>().sort(dataToBeSorted);
return;
}
merge(left, right, dataToBeSorted);
}

public static<T> void sort(LinkedList<T> dataToBeSorted){
if (dataToBeSorted.size() < 2)
return;
var temp=new Test<T>();
temp.divide(dataToBeSorted);
temp.executor.shutdownNow();
}

编辑部分:

上述代码已更新。

  • 我添加了future,并试图用另一种方法关闭它。现在我得到一个排序的元素,但只要我的设备可以产生线程。

  • 由于newCachedThreadPool产生无限线程,并在60sIm获得以下输出后取消这些线程:

    [1.427s][warning][os,thread] Failed to start thread - pthread_create failed (EAGAIN) for attributes: stacksize: 1024k, guardsize: 0k, detached.

  • 当将newCachedThreadPool更改为newFixedThreadPool(Runtime.getRuntime().availableProcessors())时,我将不会得到任何输出!。

您的解决方案是多线程的,并创建了大量中间数据结构,请理解,它很可能比优化后的单线程实现慢得多。特别是在最后,由于采用了合并式的处理方式,内存被访问,东西被移动到任何地方。基本上,该算法将受到主内存性能/缓存而非CPU的限制,除非比较成本巨大。

但从技术上讲,您的实现不是线程安全的,并且没有等待子任务完成。

所以典型的var左&right可能稍后由另一个线程进行排序,但会立即合并,而无需等待单个排序结果。

您需要进行合并以等待left&先排序,然后再合并结果。

如果不等待,将在非线程安全的数据结构上同时执行,程序将错误地运行。

我最终做了以下事情:

  • 我添加了future,并试图用另一种方法关闭它。现在我得到一个排序的元素,但只要我的设备可以产生线程。

  • 我使用了newWorkStealingPool,通过使用偷工作的概念,我可以在不遇到内存问题的情况下对大数据进行排序。

我的解决方案最终是这样的:

public class ExecutorMergeSorter<T> implements Comparable<T> {
private final ExecutorService excr;
public ExecutorMergeSorter() {
excr = Executors.newWorkStealingPool();
}
private void divide(LinkedList<T> dataToBeSorted) {
if (dataToBeSorted.size() < 2) {
return;
}
int mid = dataToBeSorted.size() / 2;
LinkedList<T> left = new LinkedList<>(dataToBeSorted.subList(0, mid));
LinkedList<T> right = new LinkedList<>(dataToBeSorted.subList(mid, dataToBeSorted.size()));
Future<?> f1= (excr.submit(() -> divide(left)));
Future<?> f2= (excr.submit(() -> divide(right)));
try {
f1.get();
f2.get();
} catch (InterruptedException | ExecutionException e) {
new SeqMergeSorter<T>().sort(dataToBeSorted);
}
merge(left, right, dataToBeSorted);
}

public static<T> void sort(LinkedList<T> dataToBeSorted){
if (dataToBeSorted.size() < 2)
return;
var temp=new ExecutorMergeSorter<T>();
temp.divide(dataToBeSorted);

最新更新