2012-05-17 13 views
5

Lütfen aşağıdaki kodda Thread sızıntısı nedenini bulmama yardım edin. TestThread, run() tamamlandıktan sonra (tescilli yazdırma ifadesinden doğrulanmış) ve ana yöntem çıktıktan sonra bile (print statement ve profiler aracından doğrulanmış) çöp toplamaz. Bununla birlikte, TestThreadTestThread, bir Daemon Thread i.e. t.setDaemon(true) olarak ayarlanmışsa toplanan çöpü alır. Aşağıdaki kod, yalnızca uygulamamdaki sorunu gösteren örnek bir koddur. Önceden varolan zamanlama sınıfını (ScheduledExecutorService kullanarak başka biri tarafından tasarlanmış) kullanmaya çalışıyorum. Birden fazla Runnable s sınıfla zamanlamaya devam ettiğimde, oluşturulan iş parçacıklarının asla çöp toplanmamasını fark ettim.Neden UserThread ScheduleExecutorService ile çalışan çöp toplamaz

public class ThreadTest { 

    static void runThreadWithExecutor() { 
    final String name = "TestThread"; 
    ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(
     new ThreadFactory() { 
      @Override 
      public Thread newThread(Runnable r) { 
      Thread t = new Thread(r, name); 
      t.setDaemon(false); 
      return t; 
      } 
     }); 

    ses.schedule(new Runnable() { 
     @Override 
     public void run() { 
      System.out.println("entered " + name); 
      System.out.println("exiting " + name); 
     }}, 
     2, 
     TimeUnit.SECONDS); 
    } 

    public static void main(String[] args) throws InterruptedException { 
    System.out.println("entered main"); 
    runThreadWithExecutor(); 
    Thread.sleep(5000); 
    System.out.println("exiting main"); 
    } 
} 

cevap

5

planladığınız sonra bu son işin size infaz hizmeti shutdown() çağıran olmadığını olmasından kaynaklanmaktadır:

ses.schedule(...); 
// this stops any management threads but existing jobs will still run 
ses.shutdown(); 

Sadece kodunuza shutdown() çağrı eklendi ve onu çıkar ince. Bu, tüm ExecutorService s için geçerlidir. Kapanma olmadan, iş parçacığı havuzu daha fazla işin gönderilmesini beklemeye devam eder ve hiçbir zaman GC'lenmez.

Daha fazla ayrıntı için @ John'un yanıtını aşağıya bakın.

3

@Gray değerlendirmesiyle doğrudur Sadece neden doğru olduğunu eklediğimi anladım. ExecutorService, konuları yeniden kullanacak bir iş parçacığı havuzudur. Çalıştırma yöntemi iş parçacığı tamamlandığında 'dan farklı olarak Bir Executable Runnable işlemi tamamlandığında, iş parçacığı burada oturacak ve gönderilecek ve kullanılacak başka bir çalıştırılabilir görevi bekleyecek. Böylece kapatılarak, yürütücünün iş parçacığı havuzundaki tüm Konuları sonlandırmasını söylersiniz.

Son bölümünüze cevap vermek için. Bunu daemon'a ayarlamak, sadece başka (non-daemon) iş parçacığı çalıştığı için çalışır. Uygulamanız başka bir non daemon iş parçacığı başlattıysa, Execution iş parçacığı devam edecektir. Sadece daemon dizileri çalışırken bir daemon dizisinin öldürüleceğini hatırla.

+2

İyi bilgi John. Bir tweak. 'stop()', tüm işlerin bitişi tamamlanana kadar iş parçacığı havuzundaki tüm iş parçacıklarını sonlandırmaz. – Gray

+0

@Gray Good point –

+0

Teşekkürler çocuklar. İlk başta kabul ettiğim cevap olarak seçtim, daha sonra Grase'ı seçtim, çünkü bu cevap Gray'in olmadan açıklayıcı değil. Ancak bu yanıt bana, kodu güvenle değiştirmek için gereken tüm açıklamayı verdi :) ve işe yarıyor! – Kes115