2012-04-24 47 views
0

考慮在C中,其中i明確地預分配堆棧上N個節點結構作爲一個池或節點的堆疊使用鏈表爲例,而不是使用慢mallocs和釋放,(我不需要在運行釋放的節點所以堆棧會做的功能):預分配存儲器的棧上的對象,而然後在堆中JAVA

#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; 
} 

當我試圖immitate上述想法在Java中,多數民衆贊成我想出了...可以你完成這個類來使Node []堆棧成爲一個節點對象數組,這個對象的內存是在STACK中預分配的?

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++]; 
    } 
} 

Basiclly我想知道這一點,因爲我知道我想從我的程序能夠做到的,我知道,我不需要釋放和重複使用的內存塊的能力,我想成爲即使當我的程序幾乎有HEAP OVERFLOW時,也能夠快速地分配Node對象。節點與N的最大容量和運行指標和我一樣會是非常適合我的堆棧...

回答

6

號Java並沒有一個明確的機制,在棧上分配內存。

使用new是分配內存的唯一途徑。然後由JVM決定內存來自哪裏,並從這一點進行管理。

編輯:我剛剛在你的代碼仔細看看。你甚至沒有在堆棧上分配內存。你似乎在做的是有一個棧數據結構,它存在於數據段中,並且你自己管理。

在Java中,有沒有直接的當量:

node Stack[N]; 

換句話說,沒有辦法來構造一個連續的內存塊N對象。您必須分配一個N引用數組,然後創建N對象。

這就是說,要記住,在現代JVM,new基本上相當於一個指針腫塊。這是:(a)便宜; (二)類似於你在做什麼sp

+0

「使用新的動態分配內存的唯一途徑」,但我不試圖動態分配的,有沒有可能呢? – 2012-04-24 14:30:52

+0

@OfekRon:正如我所說的,沒有機制強制JVM在堆棧上分配內存。 – NPE 2012-04-24 14:33:47

+0

@你的編輯,最新的差異?據我所知,在程序中聲明的所有變量(糾正我,如果我是錯誤的)正在堆棧中分配內存。 (由編譯器) – 2012-04-24 14:42:12

1

你能完成這個類,使Node []成爲STACK中節點對象的數組嗎?

否。Java根據自己的啓發式爲您管理內存分配。據我所知,JLS中沒有任何東西可以保證特定對象的分配位置。

我給你的問題是 - 爲什麼你想要這個被分配到堆棧上?基於垃圾收集器的內部狀態,你認爲自己比熱點更好地知道這個數據的最高性能位置嗎? (基於我公認的非專業知識,這些對象最好放置在堆上的Eden池中。)

您需要學習Java的一件事是只是放手,並且相信虛擬機關於在哪裏分配內存的決定。只要你避免寫錯綜複雜的算法,它通常在這些決策方面確實做得很好(通常比開發人員要好),因爲它認爲信息在運行時可用,而不是在編寫代碼時被迫使用靜態二分法。)

+0

這是因爲我知道我想從我的程序中能夠做什麼,並且我知道我不需要釋放和重用一塊內存的功能,我希望能夠快速地分配一個Node對象,甚至可以作爲lightining當我的程序幾乎有HEAP OVERFLOW。 – 2012-04-24 14:33:55

+0

多數民衆贊成正是我曾與......我的計劃就慢,因爲我分配越來越多的節點問題,同樣與C代碼上空時,我使用的malloc,而不只是預先分配 – 2012-04-24 14:36:30

+0

你有沒有使用分析器或'節點發生-verbose:gc'來確定慢度是否下降到新對象分配給的內存位置?一般來說,即使堆已滿,分配所需的內存塊應該是一個常量操作(在沒有碎片的情況下,這應該是這種情況)。 – 2012-04-24 15:36:34

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因爲這些都不需要這些節點擺在首位。 (做某事的最快的方法就是不做它在所有;)

+0

我嘗試儘可能避免linkedlists,尤其是在java中,但是爲了例證id而不是將一個2Billion節點排序的鏈接列表與一個4Billion節點排序的鏈接列表合併,然後與數組相同。 – 2012-04-24 14:47:55

+0

你是有犯規算什麼,並沒有做什麼,我想,事業中的數組列表,沒有什麼,我必須填寫與由新alloacated新節點ArrayList的 - 在堆上,這不是我想要的。 – 2012-04-24 14:49:07

+0

如果有60億節點鏈表你將有大約144 GB在對象開銷單獨(大約爲該對象的節點+ 16個字節報頭32個字節),如果你有十億對象的我建議使用一個斷堆內存/記錄(合併或其他) – 2012-04-24 14:51:10