2010-05-27 39 views
105

Tôi đang cố gắng đảm bảo rằng ứng dụng Java của tôi thực hiện các bước hợp lý để mạnh mẽ và một phần trong đó liên quan đến việc tắt một cách duyên dáng. Tôi đang đọc về shutdown hooks và tôi thực sự không biết cách sử dụng chúng trong thực tế.Ví dụ hữu ích về móc tắt trong Java?

Có ví dụ thực tế nào không? Hãy nói rằng tôi đã có một ứng dụng thực sự đơn giản như thế này dưới đây, mà viết số vào một tập tin, 10 đến một dòng, theo lô 100, và tôi muốn chắc chắn rằng một đợt nhất định kết thúc nếu chương trình bị gián đoạn. Quay lại đầu trang Tôi nhận được làm thế nào để đăng ký một cái móc tắt máy nhưng tôi không có ý tưởng làm thế nào để tích hợp vào ứng dụng của tôi. Bất kỳ đề xuất?

package com.example.test.concurrency; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.PrintWriter; 

public class GracefulShutdownTest1 { 
    final private int N; 
    final private File f; 
    public GracefulShutdownTest1(File f, int N) { this.f=f; this.N = N; } 

    public void run() 
    { 
     PrintWriter pw = null; 
     try { 
      FileOutputStream fos = new FileOutputStream(this.f); 
      pw = new PrintWriter(fos); 
      for (int i = 0; i < N; ++i) 
       writeBatch(pw, i); 
     } 
     catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     finally 
     { 
      pw.close(); 
     }  
    } 

    private void writeBatch(PrintWriter pw, int i) { 
     for (int j = 0; j < 100; ++j) 
     { 
      int k = i*100+j; 
      pw.write(Integer.toString(k)); 
      if ((j+1)%10 == 0) 
       pw.write('\n'); 
      else 
       pw.write(' '); 
     } 
    } 

    static public void main(String[] args) 
    { 
     if (args.length < 2) 
     { 
      System.out.println("args = [file] [N] " 
        +"where file = output filename, N=batch count"); 
     } 
     else 
     { 
      new GracefulShutdownTest1(
        new File(args[0]), 
        Integer.parseInt(args[1]) 
      ).run(); 
     } 
    } 
} 

Trả lời

134

Bạn có thể làm như sau:

  • Hãy để móc tắt thiết lập một số AtomicBoolean (hoặc boolean dễ bay hơi) "keepRunning" false
  • (Tùy chọn, .interrupt các chủ đề làm việc nếu họ chờ đợi dữ liệu trong một số cuộc gọi chặn)
  • Đợi các chủ đề hoạt động (thực hiện writeBatch trong trường hợp của bạn) để hoàn tất, bằng cách gọi phương thức Thread.join() về các chuỗi làm việc.
  • Chấm dứt chương trình

Một số mã sơ sài:

  • Thêm một static volatile boolean keepRunning = true;
  • Trong run() bạn thay đổi để

    for (int i = 0; i < N && keepRunning; ++i) 
        writeBatch(pw, i); 
    
  • Trong chính () bạn thêm:

    final Thread mainThread = Thread.currentThread(); 
    Runtime.getRuntime().addShutdownHook(new Thread() { 
        public void run() { 
         keepRunning = false; 
         mainThread.join(); 
        } 
    }); 
    

Đó là khoảng cách tôi làm một duyên dáng "từ chối tất cả các khách hàng sau khi nảy Control-C" trong thiết bị đầu cuối.


Từ the docs:

Khi máy ảo bắt đầu chuỗi shutdown của nó sẽ bắt đầu tất cả các móc shutdown đăng ký theo một trật tự xác định và để chúng chạy đồng thời. Khi tất cả các móc đã hoàn thành, sau đó nó sẽ chạy tất cả các finalizers uninvoked nếu finalization-on-exit đã được kích hoạt. Cuối cùng, máy ảo sẽ dừng lại.

Đó là, một cái móc shutdown giữ JVM chạy cho đến khi móc đã chấm dứt (trở về từ các run() -method.

+11

Ah - vì vậy nếu tôi hiểu đúng, ý chính của những gì bạn đang nói là móc tắt có cơ hội giao tiếp với các chủ đề hiện đang chạy khác và để tắt máy ảo (ví dụ bằng cách sử dụng Thread.join()) cho đến khi nó được hài lòng rằng một dọn dẹp nhanh chóng đã được hoàn thành. Đó là điểm tôi đã mất tích. cảm ơn! –

+1

Có. Bạn hiểu rồi. Đã cập nhật câu trả lời bằng một vài câu từ tài liệu. – aioobe

+1

Xin lỗi trước, nhưng không nên GracefulShutdownTest1 triển khai Runnable? – Victor