Java冷知識:finally中的代碼必定會執行嗎?

前言

Java開發中,正常狀況下,在執行了try代碼塊以後,finally中的代碼必定會執行。咱們實際開發也常常會利用這個特性,在finally中來執行一些特殊的操做,好比:釋放資源、釋放鎖等。java

demo線程

public class Finally {
    public static void main(String[] args) {
        try {
            //正常業務邏輯
            System.out.println("I am try");
            throw new RuntimeException("I am RuntimeExecption");
        } catch (Exception e) {
            //異常處理
            System.out.println("I am Exception -> " + e.getMessage());
        } finally {
            //釋放資源等
            System.out.println("I am Finally");
        }
    }
}

executecode

I am try
I am Exception -> I am RuntimeExecption
I am Finally

那麼是否是finally中的代碼必定會被執行呢?資源

其實否則,目前做者瞭解到有兩種狀況下,finally中的代碼不會被執行(不考慮try以前出現異常或者return的狀況,換言之,在try以前出現異常或者return時,try對應的finally中的內容不會被執行)開發

finally以前虛擬機被中止

demoget

public class Finally {
    public static void main(String[] args) {
        try {
            //正常業務邏輯
            System.out.println("I am try");
            throw new RuntimeException("I am RuntimeExecption");
        } catch (Exception e) {
            //異常處理
            System.out.println("I am Exception -> " + e.getMessage());
            System.exit(1);//異常關閉虛擬機
        } finally {
            //釋放資源等
            System.out.println("I am Finally");
        }
    }
}

execute虛擬機

I am try
I am Exception -> I am RuntimeExecption

上面的代碼在出現了異常以後,使用System.exit(1)退出關閉虛擬機,finally中的代碼固然沒法執行。it

守護線程中的finally

demoio

public class Finally {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    //正常業務邏輯
                    System.out.println("I am try");
                    Thread.sleep(1000);
                } catch (Exception e) {
                    //異常處理
                    System.out.println("I am Exception -> " + e.getMessage());
                } finally {
                    //釋放資源等
                    System.out.println("I am Finally");
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(1000);
        System.out.println("end");
    }
}

executeclass

I am try
end

使用setDaemon(true)方法來設置線程爲守護線程,從打印結果中能夠看到,守護線程中,try代碼塊中的代碼執行了,finally代碼塊未必執行。主要緣由是由於守護線程會隨着全部非守護線程的退出而退出。上述在主線程和守護線程中都設置sleep(1000)的緣由是怕線程run()方法還未開始執行主線程就退出了,這樣的話try代碼塊中的內容都不會執行。固然不是說守護線程中的finally代碼必定不會執行。

總結

java中,若是想要執行try中的代碼以後,不容許再執行finally中的代碼,有如下兩種方式:

  • 使用System.exit(1)來退出虛擬機
  • 把當前執行trycatchfinally代碼的線程設置爲守護線程
相關文章
相關標籤/搜索