【发布时间】:2017-09-28 11:18:43
【问题描述】:
我有 Collector 和 ThreadLocalScope 这样的课程:
Collector {
Collector() {
events = new LinkedList<>();
}
add(Event e) {
events.add(e);
}
flush() {
LinkedList<Event> copy = events;
new Thread(() -> {
for (Event e : copy) {
sendToServer(e);
}
copy.clear();
).start();
events = new LinkedList<>();
}
}
ThreadLocalScope {
public static ThreadLocal<Collector> local = new ThreadLocal<>() {
protected Collector initialValue() {
return new Collector();
}
}
}
Collector 只是添加事件,并在调用flush 时将这些事件发送到新线程中的 API。 Collector 在 ThreadLocal 中初始化。
我还有一个多次执行的 Job 类(使用 Quartz)。当这样定义时,一切都很好:
Job {
execute() {
for (int i = 0; i < 100,000; i++) {
ThreadLocalScope.get().add(new Event());
}
ThreadLocalScope.get().flush();
}
}
但是,如果我像这样坚持收集器:
Job {
Collector collector;
Job() {
collector = ThreadLocalScope.get();
}
execute() {
for (int i = 0; i < 100,000; i++) {
collector.add(new Event());
}
collector.flush();
}
}
我看到我的旧代内存使用量迅速增加,并且停止世界垃圾收集循环一直在发生。唯一的区别是我添加了Collector 作为成员变量,而不是每次都调用ThreadLocalScope.get()。
增加可能只意味着事件被移到老年代。但为什么会这样呢? Collector 会立即清除它对事件的所有引用,所以即使它没有被 GC,事件也应该是。
【问题讨论】: