2010-03-11 26 views
69

Câu hỏi này đã được đăng trên một số trang web. Tôi đã không tìm thấy câu trả lời đúng ở đó, vì vậy tôi đăng nó ở đây một lần nữa.Java Thread Garbage được thu thập hay không

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

Truy vấn của tôi không phải là dừng Chủ đề. Hãy để tôi thuật lại câu hỏi của tôi. Dòng A (xem mã ở trên) bắt đầu một Chủ đề mới; và Dòng B làm cho tham chiếu chuỗi rỗng. Vì vậy, JVM bây giờ có một đối tượng Thread (đang ở trạng thái đang chạy) mà không có tham chiếu nào tồn tại (như t = null trong dòng B). Vì vậy, câu hỏi của tôi là, tại sao luồng này (không có tham chiếu nữa trong chuỗi chính) tiếp tục chạy cho đến khi luồng chính đang chạy. Theo hiểu biết của tôi, đối tượng chủ đề phải là bài đăng được thu thập rác B. Tôi đã cố gắng chạy mã này trong 5 phút và hơn thế nữa, yêu cầu Java Runtime chạy GC, nhưng luồng chỉ không dừng lại.

Hy vọng cả mã và câu hỏi đều rõ ràng trong lần này.

Trả lời

102

Chủ đề đang chạy được coi là một bộ sưu tập rác gốc được gọi là rác và là một trong những thứ giữ cho nội dung không bị thu gom rác. Khi bộ thu gom rác xác định xem đối tượng của bạn là 'reachable' hay không, nó luôn luôn làm như vậy bằng cách sử dụng bộ rễ thu gom rác làm điểm tham chiếu.

Hãy xem xét điều này, tại sao chủ đề chính của bạn không bị thu gom rác, không ai đang tham chiếu một trong hai chủ đề đó.

+10

Câu trả lời này, vì nó hiện đang tồn tại, đặt ra câu hỏi nếu chủ đề có thể được GC'ed ở tất cả (sau khi họ chấm dứt). Vì câu hỏi này được đánh dấu là bản sao của [this this] (http://stackoverflow.com/questions/10380327/java-threads-and-garbage-collector), nên đề cập rằng các chuỗi sẽ không còn được đánh dấu là " rễ thu gom rác thải "sau khi chúng kết thúc, và do đó, chúng có thể tiếp cận được với GC. – bluenote10

+0

@ bluenote10 chính xác, do đó cụm từ "chạy chuỗi". – falstro

+10

Câu cuối cùng là thâm nhập: "tại sao sợi chính của bạn không bị rác ...". – Determinant

15

JVM có tham chiếu đến tất cả các chuỗi đang chạy.

Không có chủ đề nào (hoặc những thứ được đề cập đến) sẽ bị thu gom rác trong khi vẫn đang chạy.

8

Chủ đề không phải là rác được thu thập vì có các tham chiếu đến các chủ đề mà bạn không thể nhìn thấy. Ví dụ, có các tham chiếu trong hệ thống thời gian chạy.

Khi tạo chuỗi được thêm vào nhóm chủ đề hiện tại. Bạn có thể nhận được một danh sách các Threads trong nhóm thread hiện tại, vì vậy đó là một cách khác để có được một tham chiếu đến nó.

18

Như đã giải thích, chủ đề chạy, theo định nghĩa, miễn dịch với GC. GC bắt đầu công việc của mình bằng cách quét "rễ", được coi là luôn có thể truy cập được; rễ bao gồm các biến toàn cầu ("trường tĩnh" trong Java-talk) và ngăn xếp của tất cả các luồng đang chạy (có thể tưởng tượng rằng chồng của chuỗi đang chạy tham chiếu đến cá thể Thread tương ứng).

Tuy nhiên, bạn có thể tạo chuỗi chỉ là chuỗi "daemon" (xem Thread.setDaemon(boolean)). Một chuỗi daemon không được thu gom rác nhiều hơn một chuỗi không phải daemon, nhưng JVM thoát khi tất cả các luồng đang chạy là daemon. Một cách để tưởng tượng nó là mỗi luồng, khi nó kết thúc, kiểm tra xem liệu có còn một số luồng không chạy daemon; nếu không, chuỗi kết thúc sẽ thực hiện lệnh gọi System.exit(), thoát khỏi JVM (hủy bỏ các chuỗi daemon đang chạy). Đây không phải là vấn đề liên quan đến GC; theo một cách nào đó, các luồng được phân bổ thủ công. Tuy nhiên, đây là cách JVM có thể chấp nhận các luồng bán giả mạo. Điều này thường được sử dụng cho các trường hợp Timer.

Các vấn đề liên quan