【问题标题】:Threadprogramming, Heap OutOfMemory线程编程,堆内存不足
【发布时间】:2014-06-14 12:39:28
【问题描述】:

我第一次使用 Java 中的线程进行编程,所以这里有一个关于线程的初学者问题。

我的代码:

import java.util.ArrayList;
import java.util.List;

public class CollatzRunner implements Runnable {
private int lastNumber = 0;
private int highestCounter = 0;
private int highestValue = 0;

public void run() {     
    while(this.lastNumber < 1000000) {
        this.lastNumber++;
        Collatz c = new Collatz(lastNumber);
        List<Integer> values = new ArrayList<Integer>();
        while(c.hasNext()) {
            values.add(c.next());
        }

        if(this.highestCounter < values.size()) {
            this.highestCounter = values.size();
            this.highestValue = values.get(0);
        }
        //System.out.println(Thread.currentThread().getName() + ": " + this.lastNumber);
        System.out.println(Thread.currentThread().getName());
    }
}
}

和:

public class CollatzSimulator {
public static void main(String[] args) {
    CollatzRunner runner = new CollatzRunner();

    Thread t1 = new Thread(runner, "Thread-1");
    Thread t2 = new Thread(runner, "Thread-2");
    Thread t3 = new Thread(runner, "Thread-3");
    Thread t4 = new Thread(runner, "Thread-4");
    //Thread t5 = new Thread(runner, "Thread-5");
    //Thread t6 = new Thread(runner, "Thread-6");
    //Thread t7 = new Thread(runner, "Thread-7");
    //Thread t8 = new Thread(runner, "Thread-8");

    t1.start();
    t2.start();
    t3.start();
    t4.start();
    //t5.start();
    //t6.start();
    //t7.start();
    //t8.start();

    System.out.println("bla");
}   
}

运行此代码时,如果几乎立即得到 OutOfMemoryError: Heap space。所以我怀疑我在这里遇到了相当大的内存泄漏。问题是我在这个领域没有经验,所以我在这个网站上问。

到目前为止我已经尝试过: - 做了一个堆空间转储文件(在 5 秒内生成 800MB) - 在使用 Collat​​z 实例终止引用后尝试将其设置为 null,希望垃圾收集器能够释放堆空间。

我的程序只是一个小类 Collat​​z,它为给定数字生成 collat​​zsequence,我想使用线程为 0

感谢您的帮助!

【问题讨论】:

  • 你到底为什么要制作 1000000 个 Collat​​z 对象?当然会崩溃,哈哈。
  • 你试过只用一个Thread来运行这个吗?我很确定它无论如何都会崩溃,并且崩溃不是由线程问题引起的(尽管此代码会在竞争条件方面存在问题)
  • @Zhuinden:因为我们的任务是写一个类,可以计算给定数的collat​​z序列,我需要通过线程计算所有collat​​z序列,最多1mio​​。
  • @aRestless:是的,我们已经尝试过了。它会根据您本地计算机上的堆空间崩溃。在我们的笔记本电脑上,它开始在大约 150.000 个对象处崩溃。
  • 你不能只创建一个 Collat​​z 对象吗?

标签: java multithreading out-of-memory


【解决方案1】:

我很确定问题可以在这里找到:

List<Integer> values = new ArrayList<Integer>();
while(c.hasNext()) {
    values.add(c.next());
}

据我了解,Collat​​z 序列可能会非常长。 c.next() 所做的是计算序列的下一个成员,这几乎不使用任何空间。但是将所有序列成员连接到一个列表中会占用大量空间。您创建的线程越多,您就越早遇到障碍。

如果您没有为堆分配大量空间的选项,我很确定唯一的选择是写出values 列表的一部分一旦文件超过特定长度(无论如何你必须在某个时候输出它)。然而,有了这么多 I/O,多线程的使用将毫无意义

【讨论】:

    【解决方案2】:

    为了确定给定起始值的 Collat​​z 序列的长度:不要存储序列,只需计算 Collat​​z 返回的值的数量:

    Collatz c = new Collatz(lastNumber);
    int length = 0;
    while(c.hasNext()) {
        length++;
    }
    
    if(this.highestCounter < length) {
        this.highestCounter = length;
        this.highestValue = lastNumber;
    }
    

    稍后

    在阅读了“线程”挑战之后:如果您的计算机具有多个内核,那么通过并行运行多个线程(内核数)来尝试搜索最长可达 1M 的 Collat​​z 序列是有意义的, 但不使用完全相同的代码。将参数 startValue 和 increment 添加到 Collat​​z runner 并为每次迭代添加这个,这样第一个线程,比如 4,计算 1、5、9,...第二个 2、6、10,...第三个 3 , 7, 11,... 和第四个 4, 8, 12,....

    【讨论】:

    • values.get(0) 应该替换为 lastNumber,我猜。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    • 2017-11-09
    • 2013-09-10
    相关资源
    最近更新 更多