Может ли GC собрать мою переменную здесь, даже если я использую ее в другом потоке? - PullRequest
0 голосов
/ 13 декабря 2011

Предположим, я создаю экземпляр этого Test класса, который запускает новый поток, используя вложенный класс:

public class Test
{
    private String _str;

    public Test()
    {
        _str = "Hello world !";
        new TestThread().start(); // Start a background thread
    }


    private class TestThread extends Thread
    {
        public void run()
        {
            while (true)
            {
                System.out.println(_str);
                Thread.sleep(1000);
            }
        }
    }
}

Что произойдет, если я удалю какие-либо сильные ссылки на мой экземпляр Test? Фоновый поток все еще будет активен и будет продолжать печатать переменную _str, но я боюсь, что GC может собрать его в любое время.

Конечно, я могу создать локальную копию ссылки (с помощью конструктора: public TestThread(String str) и сохранить ее в локальной переменной), но мне интересно, если это необходимо.

Ответы [ 2 ]

5 голосов
/ 13 декабря 2011

TestThread само по себе имеет сильную ссылку на Test, поэтому до тех пор, пока оно не подлежит сбору, экземпляр Test не будет собираемым.Поскольку это работающий поток, экземпляр TestThread, очевидно, недоступен для сбора.

Когда вы создаете нестатический внутренний класс (TestThread), каждый экземпляр этого класса имеет неявный ссылка на экземпляр включающего его класса (Test).

См. раздел «Внутренние классы» в руководстве по Java для вложенных классов .

У вас нет«бояться» того, что может сделать ГК.Он не будет собирать объект, на который вы могли бы ссылаться, если только вы не собираетесь работать со слабыми ссылками.

1 голос
/ 13 декабря 2011

Вам не нужно беспокоиться о gc, но видимость _str в памяти не гарантируется.

Вам нужно, чтобы _str был конечным или изменчивым, чтобы TestThread видел правильное значение. Также вам нужно запустить поток после конструктора. Текущий код позволяет получить доступ к указателю this из другого потока до завершения работы конструктора, что делает недействительными гарантии для final.

Хранение копии _str в TestThread (как вы упомянули) в качестве конечной переменной, а затем создание TestThread статическим классом разрешит все это.

...