2012-04-30 31 views
17

thể trùng lặp:
Java Thread Garbage collected or notJava đề và rác thu

Hãy xem xét các lớp sau đây:

class Foo implements Runnable { 

    public Foo() { 
     Thread th = new Thread (this); 
     th.start(); 
    } 

    public run() { 
    ... // long task 
    } 

} 

Nếu chúng ta tạo ra một số trường hợp của Foo bằng cách làm

new Foo(); 
new Foo(); 
new Foo(); 
new Foo(); 

(lưu ý rằng chúng tôi không giữ con trỏ cho họ).

  1. những trường hợp có thể được loại bỏ bằng các bộ thu rác trước thread trong run() kết thúc? (Nói cách khác: là có bất kỳ tài liệu tham khảo đến Foo đối tượng?)

  2. Và, trong Mặt khác, những trường hợp đó sẽ được gỡ bỏ bởi GC sau khi thread trong `run()' kết thúc, hoặc là chúng ta lãng phí bộ nhớ ("rò rỉ bộ nhớ")?

  3. Nếu một trong hai hoặc 2. là một vấn đề, cách thích hợp để làm điều đó là gì?

Cảm ơn

+0

Bạn thực sự có thể kiểm tra điều này rất dễ dàng. –

+0

@Quaternion, có thể, nhưng từ ngữ của câu hỏi khác thực sự là "khó hiểu" và khó hiểu, imho. – cibercitizen1

+1

Đây không phải là bản sao. Câu hỏi được liên kết không đề cập đến khía cạnh của "nó sẽ là rác được thu thập sau khi hoàn thành" (Tôi sắp hỏi điều này một cách cụ thể). Nó chỉ hỏi/trả lời các khía cạnh của "nó sẽ không được GC'ed trong khi chạy". Câu hỏi này ở đây là theo ý kiến ​​của tôi tốt hơn. – bluenote10

Trả lời

16
  1. Bất kỳ đối tượng được tham chiếu bởi một chủ đề hoạt động có thể không được de-phân bổ.
  2. Có, các phiên bản sẽ bị xóa bởi GC sau khi luồng trong `run() 'kết thúc.
  3. Không có prob.
+0

Vui lòng cho tôi biết nơi bạn nhận được kết luận này. – Chao

2
  1. Đối tượng Foo được tham chiếu bởi Chủ đề. Chủ đề được tham chiếu trong suốt quá trình chạy. Vì vậy nó sẽ không được thu gom rác thải.
  2. Không có rò rỉ bộ nhớ. Chủ đề sẽ kết thúc và sẽ được thu thập rác và Foo đối tượng trong quá trình này.
  3. Nó sẽ hoạt động tốt.
10
  1. những trường hợp có thể được loại bỏ bằng các bộ thu rác trước thread trong run() kết thúc? (Nói cách khác: là có bất kỳ tham chiếu đến các đối tượng Foo?)

số Trong khi các nhà xây dựng đang chạy GC sẽ không thu thập các đối tượng. Nếu ngay cả những đơn giản nhất:

Customer c = new Customer(); 

có thể thất bại trong khi các nhà xây dựng của Customer đang chạy. Mặt khác khi bạn bắt đầu một chủ đề mới, đối tượng chuỗi sẽ trở thành một gốc GC mới, vì vậy mọi thứ được tham chiếu bởi đối tượng đó không phải là đối tượng thu thập rác.

  1. Và, trong Mặt khác, những trường hợp đó sẽ được gỡ bỏ bởi GC sau khi thread trong `run()' kết thúc, hoặc chúng ta đang lãng phí bộ nhớ ('rò rỉ bộ nhớ')?

Sau khi hoàn tất, nó không còn là gốc GC nữa. Nếu không có mã nào khác trỏ đến đối tượng chuỗi đó, nó sẽ bị thu gom rác.

  1. Nếu một trong hai hoặc 2. là một vấn đề, cách thích hợp để làm điều đó là gì?

Mã của bạn là tốt. Tuy nhiên:

  • bắt đầu một chủ đề mới trong một constructor là một ý tưởng không tồi từ thời điểm đơn vị kiểm định xem

  • giữ một tham chiếu đến tất cả các chủ đề chạy có thể có lợi nếu ví dụ bạn muốn ngắt những chủ đề này sau.

+0

@MarkoTopolnik: oh, đúng vậy! OP đang truyền 'this' tới hàm tạo' Thread', nó là một thể hiện của 'Foo'. Tuy nhiên, điều này là đúng - nếu 'Foo' có một số trạng thái, tất cả các biến trạng thái sẽ tồn tại GC vì chúng được tham chiếu bởi' Foo' - và 'Foo' được tham chiếu bởi chính chuỗi đó. –

+4

Bắt đầu một chuỗi mới trong một hàm tạo là một ý tưởng tồi từ một điểm an toàn của luồng xem. Trong trường hợp đơn giản này, có thể có vấn đề, nhưng nếu bạn phân lớp lớp và khởi tạo một số trường cuối cùng trong hàm tạo lớp con, bạn có thể kết thúc với chúng không được khởi tạo trước khi được truy cập. –

7

Bắt đầu một chủ đề mới mà không chỉ định một nhóm chủ đề sẽ add it to the default group:

Nếu nhóm là null và có một người quản lý an ninh, nhóm được xác định bằng phương pháp getThreadGroup quản lý bảo mật của. Nếu nhóm là null và không có trình quản lý bảo mật hoặc phương thức getThreadGroup của trình quản lý bảo mật trả về null, nhóm được đặt là cùng một ThreadGroup làm luồng tạo chuỗi mới.

Nhóm sẽ giữ tham chiếu đến chuỗi miễn là nó còn hoạt động, vì vậy nó không thể là GC trong thời gian đó.

Khi một chuỗi kết thúc (= khi run() trả về vì bất kỳ lý do gì), chuỗi sẽ bị xóa khỏi nhóm chuỗi. Điều này xảy ra theo phương thức riêng exit() được gọi từ mã gốc. Đây là thời điểm khi tham chiếu cuối cùng cho chuỗi bị mất và nó trở thành đủ điều kiện cho GC.

Lưu ý rằng mã cho biết rằng ThreadGroup có thể là null nhưng điều đó không đúng. Các null-kiểm tra khác nhau chỉ là để tránh NPEs trong trường hợp hiếm hoi mà một cái gì đó đi sai. Trong Thread.init(), bạn sẽ nhận được NPE nếu Java không thể xác định nhóm chủ đề.

0

Giả sử bạn đang tạo các đối tượng trong phương thức chạy, các đối tượng sẽ vượt quá phạm vi khi thoát khỏi phương thức chạy và sau đó sẽ có sẵn để thu thập rác. Chạy chỉ là một phương pháp khác. Sử dụng đề tài hay không không thay đổi hành vi thu gom rác ở đây theo bất kỳ cách nào. Tất cả những gì bạn cần quan tâm là khi các đối tượng ra khỏi phạm vi, thường được gắn với phạm vi khối (khối phương thức, trong khi vòng lặp, nếu khối, vv ..).

Vì vậy, vì bạn không giữ bất kỳ tham chiếu nào đến đối tượng để bắt đầu, bạn có thể muốn trích xuất logic tạo đối tượng thành phương thức sống ngắn của riêng nó. Bằng cách đó, đối tượng được tạo ra sẽ không cần phải được giữ ngoài phạm vi của phương thức đó.

+0

các đối tượng Foo được tạo không phải là phương thức chạy, nhưng, ví dụ, trong chính. – cibercitizen1

+0

chỉ là một khối mã khác, không thay đổi điều gì –