线程池无法创建本机线程
Threadpool unable to create native thread
我正在尝试以各种方式实施归并排序。我确实使用 fork/join
实现了它,现在我想使用 ExecutorService
和 Threadpool
.
实现它
我目前的情况如下:
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
产生无限线程并在 60s
之后取消它们,我得到以下输出:
[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())
时,我将永远不会得到任何输出!
您的解决方案是多线程并创建大量中间数据结构,请理解它很可能比更优化的单线程实现慢得多。特别是最后访问的是内存,并且由于合并排序处理方式,事物被移动到任何地方。基本上该算法将受主内存 performance/cache 而不是 CPU 的限制,除非比较成本很大。
但从技术上讲,您的实现不是线程安全的,也不会等待子任务完成。
因此,通常 var left 和 right 可能稍后由另一个线程排序,但会立即合并,而无需等待单个排序结果。
您需要合并等待左右首先排序,然后才合并结果。
如果不等待,执行将在非线程安全数据结构上并发发生,程序将运行错误。
我最后做了以下事情:
我添加了 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);
我正在尝试以各种方式实施归并排序。我确实使用 fork/join
实现了它,现在我想使用 ExecutorService
和 Threadpool
.
我目前的情况如下:
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
产生无限线程并在60s
之后取消它们,我得到以下输出:[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())
时,我将永远不会得到任何输出!
您的解决方案是多线程并创建大量中间数据结构,请理解它很可能比更优化的单线程实现慢得多。特别是最后访问的是内存,并且由于合并排序处理方式,事物被移动到任何地方。基本上该算法将受主内存 performance/cache 而不是 CPU 的限制,除非比较成本很大。
但从技术上讲,您的实现不是线程安全的,也不会等待子任务完成。
因此,通常 var left 和 right 可能稍后由另一个线程排序,但会立即合并,而无需等待单个排序结果。
您需要合并等待左右首先排序,然后才合并结果。
如果不等待,执行将在非线程安全数据结构上并发发生,程序将运行错误。
我最后做了以下事情:
我添加了 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);