避免Finalizer和Cleaner-第二章创建和销毁对象-Effective Java学习笔记07

学习笔记@Effective Java

文章内容来源于Joshua Bloch - Effective Java (3rd) - 2018.chm一书

第二章

创建和注销对象

Item 8避免Finalizer和Cleaner

// An autocloseable class using a cleaner as a safety net
public class Room implements AutoCloseable {
    private static final Cleaner cleaner = Cleaner.create();

    // Resource that requires cleaning. Must not refer to Room!
    private static class State implements Runnable {
        int numJunkPiles; // Number of junk piles in this room

        State(int numJunkPiles) {
            this.numJunkPiles = numJunkPiles;
        }

        // Invoked by close method or cleaner
        @Override public void run() {
            System.out.println("Cleaning room");
            numJunkPiles = 0;
        }
    }

    // The state of this room, shared with our cleanable
    private final State state;

    // Our cleanable. Cleans the room when it’s eligible for gc
    private final Cleaner.Cleanable cleanable;

    public Room(int numJunkPiles) {
        state = new State(numJunkPiles);
        cleanable = cleaner.register(this, state);
    }

    @Override public void close() {
        cleanable.clean();
    }
} 

正如我们前面所说的,房间的Cleaner只是用作安全网。如果客户机在try-with-resource块中包围了所有文件室实例,那么就不需要自动清理。这个行为良好的客户演示了以下行为:

public class Adult {
    public static void main(String[] args) {
        try (Room myRoom = new Room(7)) {
            System.out.println("Goodbye");
        }
    }
} 

正如你所料,运行Adult程序打印Goodbye,然后是打扫房间。但是这个行为不端的程序怎么办,它从不打扫房间?

public class Teenager {
    public static void main(String[] args) {
        new Room(99);
        System.out.println("Peace out");
    }
} 

你可能期望它打印出Peace out,然后是Cleaning room,但在我的机器上,它从不打印Cleaning room;它只是退出。这就是我们前面提到的不可预测性。规范说,“清洁器在清洁过程中的行为系统出口是特定于实现的。对于是否调用清理操作没有任何保证。”虽然规范没有说明,但对于正常的程序退出也是如此。在我的机器上,添加行垃圾回收()到青少年的主要方法足以使其在退出之前打印到Cleaning room,但不能保证您会在您的机器上看到相同的行为。

总之,不要使用Cleaner,或者在Java9之前的版本中使用终结器,除非作为安全网或终止非关键的本机资源。即便如此,也要注意不确定性和性能后果。

上一篇:Adware Zap Browser Cleaner for mac(广告清除)说明书


下一篇:强制GDM登陆界面到主显示器