import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ExecutorServiceTest {
public static void main(String args[]) {
new ExecutorServiceTest();
}
public ExecutorServiceTest() {
while (true) {
action();
}
}
public String action() {
String string = "";
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Callable() {
@Override
public String call() {
return randomString();
}
});
try {
string = future.get(1, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
}
future.cancel(true);
executor.shutdownNow();
return string;
}
public String randomString() {
return "asdhkashdkjshakdasdsahdka";
}
}
如果打开任务管理器窗口然后运行此类,您会注意到Java立即使用了大量内存。我彻底搜索并调试了类,但找不到内存泄漏。
是什么导致future.get(1, TimeUnit.MILLISECONDS);
耗尽所有系统内存然后崩溃?
答案 0 :(得分:6)
ThreadPoolExecutor
类具有非空finalize()
方法(执行池关闭),因此在进行垃圾收集时,它首先进入终结器队列(基本上是链表)并由分开&#34;终结者&#34;线。即使池没有活动任务,关闭它也很慢。根据硬件,操作系统和运行条件,新的终结器的添加速度可能比Finalizer线程处理的速度快,因此您可能会期望内存不断增长。通常,您不应该过快地创建和关闭执行程序。
答案 1 :(得分:0)
我认为罪魁祸首就在这里:
while (true) {
action();
}
这会积极地产生新线程(这是一项昂贵的操作)而且,恕我直言,这会导致内存问题和崩溃。
另外,我认为这是使用单线程执行程序的一个不好的例子。它更适合在单个后台线程中串行执行任务。如果需要添加大量必须同时执行的新任务,最好使用线程池。控制工作线程数将阻止程序内存不足。
工作代码:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ExecutorServiceTest {
ExecutorService executor = Executors.newSingleThreadExecutor();
public static void main(String args[]) {
new ExecutorServiceTest();
}
public ExecutorServiceTest() {
while (true) {
action();
}
}
public String action() {
String string = "";
if (executor.isShutdown()) {
Future<String> future = executor.submit(new Callable() {
@Override
public String call() {
return randomString();
}
});
try {
string = future.get(1, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
System.out.println(ex);
}
future.cancel(true);
executor.shutdownNow();
}
return string;
}
public String randomString() {
return "asdhkashdkjshakdasdsahdka";
}
}