0

考虑 c 中的 LinkedList 示例,其中我在堆栈上显式预分配 N 个节点结构以用作池或节点堆栈,而不是使用慢速 malloc 和释放,(我不需要在运行时释放节点的功能,所以一个堆栈会做):

#define N 40000

typedef struct node_t {
    void * ele;
    struct node_t * next;
}node,*Pnode;

node Stack[N];//memory allocation for the linkedlist nodes
int sp=0;

Pnode createNode(void * x) {
    Pnode temp=&Stack[sp++];
    temp->ele=x;
    temp->next=NULL;
    return temp;
}

当我试图在 JAVA 中模仿上面的想法时,这就是我想出的......你能完成这个类以使 Node[] 堆栈成为一个节点对象数组,其中内存是在堆栈中预分配的吗?

public class Node<E>  {

    private final static int n = 40000;
    private static Node[] stack = ?
    private static int sp = 0;

    private E ele;
    private Node next;

    private Node () {}
    public Node createNode(E e) {
        stack[sp].ele=e;
        stack[sp].next=null;
        return stack[sp++];
    }
}

基本上我想知道这一点,因为我知道我希望我的程序能够做什么,而且我知道我不需要释放和重用一块内存的能力,我希望能够快速分配一个 Node 对象即使当我的程序几乎有堆溢出时,它也能像闪电一样发光。最大容量为 N 的节点堆栈和像我一样的运行索引对我来说是完美的......

4

3 回答 3

6

不,Java 没有明确的机制来在堆栈上分配内存。

使用new是分配内存的唯一方法。然后由 JVM 来决定该内存的来源,并从那时起对其进行管理。

编辑:我刚刚仔细查看了您的代码。您甚至没有在堆栈上分配内存。您似乎正在做的是拥有一个位于数据段上的堆栈数据结构,并且您自己管理。

在 Java 中,没有直接等价于:

node Stack[N];

换句话说,没有办法N在连续的内存块中构造对象。您必须分配一个N引用数组,然后创建N对象。

也就是说,请记住,在现代 JVM 中,new基本上相当于指针碰撞。这是: (a) 便宜;(b) 类似于你正在做的事情sp

于 2012-04-24T14:28:47.257 回答
1

你能完成这个类以使 Node[] 成为堆栈中的节点对象数组吗?

不会。Java 会根据自己的启发式方法为您管理内存分配。据我所知,JLS 中没有任何内容可以保证特定对象的分配位置。

我对你的问题是 - 你为什么在堆栈上分配它?根据垃圾收集器的内部状态,您是否认为您比 Hotspot 更了解此数据的最佳性能位置?(根据我公认的非专家知识,这些对象最好放在堆上的 Eden 池中。)

您需要学习 Java 的一件事就是放手,并相信 VM 关于在何处分配内存的决定。只要您避免编写复杂的算法,它通常确实可以很好地完成这些决策(通常比开发人员做得更好,因为它考虑了运行时可用的信息,而不是在编写代码时被迫采用静态二分法。)

于 2012-04-24T14:30:07.420 回答
1

您似乎想要的是一个对象池。

一个简单的池是使用 ArrayList

public class Node<E>  {

    private final static int MAX_SIZE = 40000;
    private final static List<Node> freeNodes = new ArrayList<>();

    private E ele;
    private Node next;

    private Node () {}

    public static Node<E> acquireNode(E e) {
        Node node = freeNodes.size() > 0 
                    ? freeNodes.remove(freeNodes.size()-1) 
                    : new Node();
        node.ele = e;
        return node;
    }

    public static void freeNode(Node<E> node) {
        if(freeNodes.size() < MAX_SIZE) {
            node.next = null;
            freeNodes.add(node);
        }
    }
}

我建议不要使用必然会创建大量对象的 LinkedList,而是使用不同的结构,例如 ArrayList 或 RingBuffer,因为它们都不需要这些节点。(做某事的最快方法是根本不做;)

于 2012-04-24T14:40:44.473 回答