ตัวอย่างที่เป็นประโยชน์ของ shutdown hook ใน Java?


126

ฉันพยายามตรวจสอบให้แน่ใจว่าแอปพลิเคชัน Java ของฉันดำเนินการตามขั้นตอนที่เหมาะสมเพื่อให้มีประสิทธิภาพและส่วนหนึ่งเกี่ยวข้องกับการปิดเครื่องอย่างสง่างาม ฉันกำลังอ่านเกี่ยวกับการปิดเครื่องและฉันไม่เข้าใจวิธีใช้ประโยชน์จากมันในทางปฏิบัติ

มีตัวอย่างที่ใช้ได้จริงหรือไม่?

สมมติว่าฉันมีแอปพลิเคชั่นที่เรียบง่ายเช่นนี้ด้านล่างซึ่งเขียนตัวเลขลงในไฟล์ 10 ถึงบรรทัดเป็นชุดละ 100 และฉันต้องการให้แน่ใจว่าแบทช์ที่กำหนดจะเสร็จสิ้นหากโปรแกรมถูกขัดจังหวะ ฉันได้รับวิธีการลงทะเบียน hook การปิดระบบ แต่ฉันไม่รู้ว่าจะรวมเข้ากับแอปพลิเคชันของฉันได้อย่างไร ข้อเสนอแนะใด ๆ ?

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();
        }
    }
}

คำตอบ:


160

คุณสามารถทำสิ่งต่อไปนี้:

  • ให้ shutdown hook ตั้งค่า AtomicBoolean (หรือ volatile boolean) "keepRunning" เป็นเท็จ
  • (หรือไม่ก็ได้.interruptเธรดที่ใช้งานได้หากรอข้อมูลในการโทรบล็อก)
  • รอให้เธรดการทำงาน (ดำเนินการwriteBatchในกรณีของคุณ) เสร็จสิ้นโดยเรียกใช้Thread.join()เมธอดบนเธรดที่ใช้งานได้
  • ยุติโปรแกรม

รหัสร่างบาง:

  • เพิ่ม static volatile boolean keepRunning = true;
  • ในการทำงาน ()คุณเปลี่ยนเป็น

    for (int i = 0; i < N && keepRunning; ++i)
        writeBatch(pw, i);
  • ในmain ()คุณเพิ่ม:

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

นั่นเป็นวิธีคร่าวๆที่ฉันจะ "ปฏิเสธไคลเอนต์ทั้งหมดเมื่อกดปุ่ม Control-C" ในเทอร์มินัลอย่างสง่างาม


จากเอกสาร :

เมื่อเครื่องเสมือนเริ่มต้นลำดับการปิดเครื่องจะเริ่มการปิดเครื่องที่ลงทะเบียนไว้ทั้งหมดตามลำดับที่ไม่ได้ระบุและปล่อยให้มันทำงานพร้อมกัน เมื่อ hooks ทั้งหมดเสร็จสิ้นแล้วมันจะเรียกใช้ finalizers ที่ไม่ได้รับการเชิญทั้งหมดหากเปิดใช้งาน finalization-on-exit ในที่สุดเครื่องเสมือนจะหยุดทำงาน

นั่นคือ hook การปิดระบบจะให้ JVM ทำงานจนกว่า hook จะสิ้นสุดลง (ส่งคืนจากrun () -method


14
Ah - ถ้าฉันเข้าใจถูกสิ่งสำคัญของสิ่งที่คุณพูดคือการปิดระบบมีโอกาสที่จะสื่อสารกับเธรดอื่น ๆ ที่กำลังทำงานอยู่ในขณะนี้และเพื่อระงับการปิด VM (เช่นโดยใช้ Thread.join () ) จนกว่าจะพอใจว่าการล้างข้อมูลอย่างรวดเร็วเสร็จสมบูรณ์ นั่นคือจุดที่ฉันขาดหายไป ขอบคุณ!
Jason S

2
ใช่. คุณเข้าใจแล้ว อัปเดตคำตอบด้วยสองสามประโยคจากเอกสาร
aioobe

1
ขออภัยล่วงหน้า แต่ GracefulShutdownTest1 ใช้ Runnable หรือไม่
วิกเตอร์

สิ่งนี้จะใช้งานได้หรือไม่เมื่อเริ่มต้น GUI ในเธรดหลัก ฉันรู้ว่ามันไม่ใช่วิธีที่ดีที่สุดที่จะทำ (ใช้ EDT แทน) แต่ฉันกำลังทำงานกับโค้ดเก่า
Agostino

1
@ MartynasJusevičius, JVM จะสิ้นสุดเมื่อเธรดที่ไม่ใช่ daemon ทั้งหมดสิ้นสุดลง หากmainThreadเธรดเป็น daemon การjoinรับประกันว่าเรารอให้เสร็จสิ้นก่อนที่จะปล่อยให้ JVM ปิดตัวลง
aioobe

-9

Shutdown Hooks เป็นเธรดที่ไม่ได้เริ่มต้นซึ่งลงทะเบียนกับ Runtime.addShutdownHook () JVM ไม่ให้การรับประกันใด ๆ เกี่ยวกับลำดับการเริ่มการทำงานของ hooks สำหรับข้อมูลเพิ่มเติมโปรดดูที่http://techno-terminal.blogspot.in/2015/08 /shutdown-hooks.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.