2016-08-30 16 views
9

Tôi có một ứng dụng khởi động bộ hẹn giờ để mở một tin nhắn trên các hành động của người dùng. Trong hồ sơ JDK có vẻ như tất cả các chủ đề khác đang được gỡ bỏ sau khi thực hiện bởi GC (tôi đoán) nhưng bộ tính giờ tạo ra không bị xóa. Điều gì có thể xảy ra ở đó?Java - Bộ hẹn giờ không bị xóa sau khi thực hiện

hẹn giờ của tôi:

/** 
* @param owner 
* @param added 
*/ 
public static void splashParentWithAnimation(AnchorPane owner, Parent added,double posX,double posY) { 
    // addParentWithAnimation(owner, added); 
    owner.getChildren().add(added); 

    AnchorPane.setLeftAnchor(added, posX); 

    AnchorPane.setTopAnchor(added, posY); 

    FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
    ft1.setFromValue(0.0); 
    ft1.setToValue(1.0); 
    ft1.play(); 


    Timer messagePrinter = new Timer(); 
    messagePrinter.schedule(new TimerTask() { 

     @Override 
     public void run() { 
      Platform.runLater(() -> { 

       if (!owner.getChildren().contains(added)) 
        return; 

       FadeTransition ft1 = new FadeTransition(Duration.millis(300), added); 
       ft1.setFromValue(1.0); 
       ft1.setToValue(0.0); 
       ft1.play(); 
       ft1.setOnFinished((e) -> { 

        if (owner.getChildren().contains(added)) 
         owner.getChildren().remove(added); 
       }); 

      }); 

     } 
    }, 1000); 
} 

JDK profiler: enter image description here

Có phải vì tôi đang sử dụng một phương pháp tĩnh hay tôi nên phá hủy nó bản thân mình?

Trả lời

7

Thực tế, bạn không gặp vấn đề gì với việc chấm dứt hẹn giờ tại đây. Các chủ đề bạn nhìn thấy trong hồ sơ đã được chấm dứt – họ có một hộp màu trắng ở phía bên trái mà chỉ ra rằng họ đã chết.

Trình hồ sơ hiển thị tất cả các chuỗi đã được tạo trong quá trình thực hiện chương trình, ngay cả khi các luồng đó đã chết và thu thập rác.

Bạn có thể dễ dàng xác nhận rằng bằng cách làm như sau: Thay vì lambda, hãy tạo một lớp con của TimerTask sẽ thực hiện tương tự và xác định lại phương thức finalize() của nó để in. Bạn sẽ thấy rằng khi các bộ sưu tập rác được thực hiện, nhiệm vụ của bạn được hoàn thành. Nó chỉ có thể xảy ra nếu chủ đề được dừng lại, bởi vì nó là nơi duy nhất trong lớp Thread nơi nó giảm tham chiếu đến Runnable của nó (trong đó TimerTask thực hiện).

Một cách khác để xác nhận đó chỉ là chọn 'Chủ đề trực tiếp' từ danh sách thả xuống Chế độ xem ở đầu bảng.

Ngoài ra, tôi khuyên bạn nên thay thế Timer để có điều gì đó tốt hơn. Nó quá lãng phí để tạo ra một chủ đề mỗi khi bạn cần phải trì hoãn một số nhiệm vụ. Có một cái nhìn tại ScheduledThreadPoolExecutor, có vẻ như nhiều hơn thích hợp cho công việc của bạn:

// Create a shared executor with a single thread 
private final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 

// Instead of creating a Timer, schedule the task 
executor.schedule(() -> { 
    // Do what you need here 
}, 1, TimeUnit.SECONDS); 

// Don't forget to terminate the scheduler when you don't need it anymore 
scheduler.terminate(); 

Bạn có thể thêm nhiều hơn một thread để người thi hành nếu bạn có quá nhiều nhiệm vụ theo lịch trình cùng một lúc và những nhiệm vụ không đủ nhỏ.

+0

tôi không chắc chắn về điều đó nhưng tốt để biết, anyways, tôi sử dụng thời gian của javaFX thay vì đó (ít nhất là cho tôi) là tốt hơn –

2

Đó là vì bạn cần phải định giờ hẹn giờ theo cách thủ công.

Nếu bạn sử dụng java.util.Timer, bạn cần gọi tới phương thức cancel để nhận tài nguyên miễn phí.

+0

bạn có thể nói như thế nào không? –

+0

name_of_timer.cancel(); ? –

+0

Có. Trong trường hợp này 'messagePrinter.cancel();' – talex

1

Bộ hẹn giờ của bạn được tạo bằng chuỗi không phải daemon, các chuỗi không phải daemon có thể chặn việc chấm dứt chương trình của bạn. Bạn nên sử dụng hàm khởi tạo cho Timer làm cho nó sử dụng một chuỗi daemon.

boolean daemon=true; Timer messagePrinter = new Timer(daemon);

Nhưng tôi sẽ sử dụng một ExecutorService như Andrew Lygin gợi ý.

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