Java İş Parçacığı Çöpü toplandı veya toplanmadı


85

Bu soru bazı sitelerde yayınlandı. Orada doğru cevapları bulamadım, bu yüzden buraya tekrar gönderiyorum.

public class TestThread {
    public static void main(String[] s) {
        // anonymous class extends Thread
        Thread t = new Thread() {
            public void run() {
                // infinite loop
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    // as long as this line printed out, you know it is alive.
                    System.out.println("thread is running...");
                }
            }
        };
        t.start(); // Line A
        t = null; // Line B
        // no more references for Thread t
        // another infinite loop
        while (true) {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            System.gc();
            System.out.println("Executed System.gc()");
        } // The program will run forever until you use ^C to stop it
    }
}

Sorgum bir İş Parçacığını durdurmakla ilgili değil. Sorumu yeniden ifade etmeme izin verin. Satır A (yukarıdaki koda bakın) yeni bir Konu başlatır; ve B Hattı, iş parçacığı referansını boş yapar. Bu nedenle, JVM artık referans olmayan (B Satırında t = null gibi) bir Konu Nesnesine (çalışır durumda olan) sahiptir. Öyleyse sorum şu, bu iş parçacığı (artık ana iş parçacığında referansı olmayan) neden ana iş parçacığı çalışana kadar çalışmaya devam ediyor. Anladığım kadarıyla, iş parçacığı nesnesi B Satırından sonra çöp olarak toplanmış olmalıydı. Bu kodu 5 dakika ve daha fazla çalıştırmayı denedim, Java Runtime'dan GC'yi çalıştırmasını istedim, ancak iş parçacığı durmuyor.

Umarım bu sefer hem kod hem de soru açıktır.

Yanıtlar:


124

Çalışan bir iş parçacığı, sözde çöp toplama kökü olarak kabul edilir ve çöplerin toplanmasını engelleyen şeylerden biridir. Çöp toplayıcı, nesnenizin ' ulaşılabilir olup olmadığını belirlediğinde ' , bunu her zaman çöp toplayıcı kökleri kümesini referans noktası olarak kullanarak yapar.

Şunu bir düşünün, ana iş parçacığınız neden çöp toplanmıyor, kimse buna da başvurmuyor.


17
Bu cevap, halihazırda olduğu gibi, konuların hiç GC'lenemeyeceği sorusunu gündeme getiriyor (sonlandırıldıktan sonra). Bu soru tekrarı olarak işaretlenmiş olduğundan bu bir , bunların sonlandırmak sonra ipler artık "çöp toplama kökleri" olarak işaretlenir ve böylece onlar GC için ulaşılabilir hale gelmesi söz edilmelidir.
bluenote10

13
Son cümle nüfuz ediyor: "ana iş parçacığın neden çöp değil ...".
Determinant

Bu nedenle, bir takip olarak, elden çıkarılmış bir iş parçacığı (birleştirilmiş olan) artık bir kök olarak kabul edilmeyecek mi? Cevabın evet olduğundan neredeyse eminim, ancak profilin altındaki uygulamamda garip şeyler görüyorum ve bu beni
meraklandırıyor

1
Ne kadar çok cevap okursam, o kadar çok kafam karışıyor, ama evet, ana iş parçacığı neden çöp toplanmıyor, üzerinde düşünülmesi gereken bir şey. Ancak ana soruya geri dönersek, eğer çocuk iş parçacığı bazı nesneler yaratırsa, ana iş parçacığı hala çalıştığından ve 'bitmiş' (!! ??) olsalar bile alt iş parçacığının referanslarını tuttuğundan GCed alınmayacaktır
Rahul Kumar

@Groostav Birleştirilen iş parçacığı çalışmıyor, bu nedenle çöp toplama kökü değil. Ancak ana iş parçacığı arandığında child.join(), bir referansı vardı child. Bu referans (ve diğerleri) atılmazsa, alt iş parçacığı GC işlemine tabi tutulamaz.
Blaisorblade

23

Açıklandığı gibi, çalışan iş parçacıkları tanım gereği GC'ye karşı bağışıktır. GC çalışmalarına her zaman ulaşılabilir olduğu varsayılan "kökleri" tarayarak başlar; kökler, genel değişkenleri (Java-talk'ta "statik alanlar") ve tüm çalışan iş parçacıklarının yığınlarını (çalışan bir iş parçacığının yığınının karşılık gelenThread örneğe ) içerir.

Bununla birlikte, bir iş parçacığını bir "arka plan programı" iş parçacığı haline getirebilirsiniz (bakınız Thread.setDaemon(boolean)). Bir arka plan programı iş parçacığı, arka plan programı olmayan bir iş parçacığından daha fazla çöp olarak toplanmaz, ancak tüm çalışan iş parçacıkları arka plan programı olduğunda JVM çıkış yapar. Bunu hayal etmenin bir yolu, her iş parçacığının, sona erdiğinde, arka planda çalışan bazı evreler olup olmadığını kontrol etmesidir; değilse, sonlandırıcı iş parçacığı System.exit()JVM'den çıkan (çalışan arka plan programı evrelerini sonlandıran) bir çağrıyı zorlar . Bu, GC ile ilgili bir sorun değildir; bir şekilde, evreler manuel olarak tahsis edilir. Bununla birlikte, JVM yarı hileli iş parçacıklarını bu şekilde tolere edebilir. Bu genellikle Timerörnekler için kullanılır .


19

JVM, çalışan tüm iş parçacıklarına bir referansa sahiptir.

Hala çalışırken hiçbir iş parçacığı (veya başvurduğu şeyler) çöp olarak toplanmayacaktır.


13

İş parçacığı, göremediğiniz iş parçacıkları için başvurular olduğundan çöp toplanmaz. Örneğin, çalışma zamanı sisteminde referanslar vardır.

İplik oluşturulduğunda, mevcut iplik grubuna eklenir. Mevcut iş parçacığı grubunda bir İş Parçacığı listesi alabilirsiniz, bu da ona bir referans almanın başka bir yoludur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.