2014-11-19 6 views
1

Я попытался написать класс для подсчета количества экземпляров в памяти. Я использовал статический атрибут - я увеличиваю его на конструкторе и уменьшаю его в методе finalize.множественный вызов финализации

Вы можете увидеть нижегородский класс.

В основном классе (TestCounter), я сделал списки счетчиков. Когда я проверить этот класс с малыми значениями (Java TestCounter 10 100) результат кажется нормальным:

Size of the list : : 0 
curently : 100 over 100 created 
Size of the list : : 0 
curently : 200 over 200 created 
Size of the list : : 0 
curently : 300 over 300 created 
Size of the list : : 0 
curently : 400 over 400 created 
Size of the list : : 0 
curently : 500 over 500 created 
Size of the list : : 0 
curently : 600 over 600 created 
Size of the list : : 0 
curently : 700 over 700 created 
Size of the list : : 0 
curently : 800 over 800 created 
Size of the list : : 0 
curently : 900 over 900 created 
Size of the list : : 0 
curently : 1000 over 1000 created 
Still 1000 instances in memory... waiting ... 
Still 1000 instances in memory... waiting ... 
Still 1000 instances in memory... waiting ... 
Still 1000 instances in memory... waiting ... 

Как я прочитал в ответ на this question, сборщик мусора не надо назвать, поэтому я называю GC явно (3 комментария строки). И теперь почти все экземпляры кажутся освободили:

curently : 10000 over 10000 created 
Still 7435 instances in memory... waiting ... 
at the end : 0 over 10000 created 

Иногда, 1 или 2 экземпляра, кажется, пребывание в памяти ...

Но если я пытаюсь с большим количеством объектов (Java TestCounter 10 100000), результаты удивительно. «Количество экземпляров» может быть отрицательным, что свидетельствует о том, что метод finalize() вызывается дважды ...

Size of the list : : 0 
curently : 896577 over 1000000 created 
Still 892834 instances in memory... waiting ... 
Still -762 instances in memory... waiting ... 
Still -762 instances in memory... waiting ... 
Still -762 instances in memory... waiting ... 

Не могли бы вы объяснить такое поведение?

Может быть, я сделал ошибку или неправильно понял что-то ...

public class Counter{ 

    static long number = 0; 
    static long totalNumber = 0; 


    public Counter(){ 
     number++; 
     totalNumber++; 

    } 

    public static long getNumber(){ 
     return number; 
    } 

    public static long getNombreTotal(){ 
     return totalNumber; 
    } 

    protected void finalize() throws Throwable{ 
      try {  
       number--; 
      } finally { 
       super.finalize(); 
      } 
    } 

} 

import java.util.ArrayList; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class TestCompteur{ 

    public static void methode(int iteration, int taille){ 

     for (int j=0; j<iteration; j++){ 

      ArrayList<Counter> liste = new ArrayList<Counter>(); 

      for (int i=0; i<taille; i++){ 
       liste.add(new Counter()); 
      } 

      liste.clear(); 

      System.out.println("Size of the list : : "+liste.size());   
      System.out.println("curently : " + Counter.getNumber() + " over " + Counter.getNombreTotal() +" created");  
     } 



    } 

    public static void main(String[] args){ 


     methode(Integer.decode(args[0]), Integer.decode(args[1])); 

     /* 
     System.gc(); 
     System.runFinalization(); 
     System.gc(); 
     */ 

     while (Counter.getNumber() != 0){ 
      //System.out.print("."); 
      System.out.println("Still " + Counter.getNumber() + " instances in memory... waiting ..."); 

        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException ex) { 
         Logger.getLogger(TestCompteur.class.getName()).log(Level.SEVERE, null, ex); 
        } 
     } 
     System.out.println("at the end : " + Counter.getNumber() + " over " + Counter.getNombreTotal() +" created"); 
    } 

} 
+0

Ваш код не является потокобезопасным. Поэтому значение 'number' может не соответствовать количеству вызовов конструктора минус количество завершающих вызовов. Попробуйте изменить «число» в синхронизированном методе или изменить его тип на AtomicInteger и посмотреть, что произойдет. – Eran

ответ

1

Я попробовал ваш код. В то время как я не получил отрицательный number, как вы делали, я застрял на:

curently : 923367 over 1000000 created 
Still 1041 instances in memory... waiting ... 
Still 1041 instances in memory... waiting ... 
Still 1041 instances in memory... waiting ... 

Тогда я синхронизирован приращений/декременты number:

public Counter() 
{ 
    incNumber(); 
    totalNumber++; 
} 

public static synchronized void incNumber() 
{ 
    number++; 
} 

public static synchronized void decNumber() 
{ 
    number--; 
} 

protected void finalize() throws Throwable 
{ 
    try { 
     decNumber(); 
    } finally { 
     super.finalize(); 
    } 
} 

В результате number достиг 0 и программа завершена.

curently : 936759 over 1000000 created 
at the end : 0 over 1000000 created 

Вывод:

finalize() не вызывается дважды для того же объекта, но когда несколько потоков (ваш главный поток и GC нить) изменить ту же переменную без синхронизации, странные вещи могут случиться.

+0

спасибо !! Конечно, я забыл проблему параллельного доступа. – user2965325

 Смежные вопросы

  • Нет связанных вопросов^_^