線程異常處理

線程異常處理

異常處理方法:

1.直接在子線程內try-catch,不能通知到主線程
2.不在子線程內try-catch,新建MyUncaughtExceptionHandler 實現Thread.UncaughtExceptionHandler,重寫uncaughtException(Thread t, Throwable e) 處理異常,不能通知到主線程
3.線程任務實現Callable接口,FutureTask包裹線程任務,可在主線程中處理線程異常
4. Executors.callable 可在主線程中處理線程異常
5.Executors.new…()生產ExecutorService executorService ,executorService 調用submit(new MyTask())產生Future實例,可在主線程中處理線程異常

一、主線程try-catch不能捕獲子線程的異常

public class ThreadSon {
    public static void main(String[] args) {
        Thread thread = null;
        try {
            thread = new Thread(new MyTask());
        } catch (Exception e) {
            System.out.println("----主線程捕獲異常: "+e.getMessage());
        }
        thread.start();
    }
    static class MyTask implements Runnable{
        @Override
        public void run() {
            try {
                System.out.println(1/0);
            } catch (Exception e) {
                System.out.println("----子線程捕獲異常: "+e.getMessage());
            }
        }
    }
}

輸出:
----子線程捕獲異常: / by zero
Process finished with exit code 0

注:1.異常處理第一種辦法:直接在子線程內try-catch,不能通知到主線程
2.JVM會調用 dispatchUncaughtException 來尋找handler進行處理。而如果沒有自定義hanlder進行處理,則會調用 System.err 進行輸出

    public void uncaughtException(Thread t, Throwable e) {
        if (parent != null) { // 父級優先處理
            parent.uncaughtException(t, e);
        } else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) { // 沒有配置handler時的處理方式
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

二、MyUncaughtExceptionHandler

package com.wx;

public class ThreadSon {
    public static void main(String[] args) {
        MyUncaughtExceptionHandler myUncaughtExceptionHandler = new MyUncaughtExceptionHandler();
        Thread thread = null;
        try {
            thread = new Thread(new MyTask());
            thread.setUncaughtExceptionHandler(myUncaughtExceptionHandler);
        } catch (Exception e) {
            System.out.println("----主線程捕獲異常: "+e.getMessage());
        }
        thread.start();
    }
    static class MyTask implements Runnable{
        @Override
        public void run() {
            System.out.println(1/0);
        }
    }
    static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.err.println("線程"+t.getName()+"捕獲異常: " + e.getMessage());
        }
    }
}

輸出:
線程Thread-0捕獲異常: / by zero
Process finished with exit code 0

三、線程任務實現Callable接口,FutureTask包裹線程任務

package com.wx;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadSon2 {
    public static void main(String[] args) {
        FutureTask<String> stringFutureTask = new FutureTask<>(new MyTask());
        Thread thread = new Thread(stringFutureTask);
        thread.start();
        try {
            String s = stringFutureTask.get();
            System.out.println("stringFutureTask返回結果:"+s);
        } catch (InterruptedException e) {
            System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
        } catch (ExecutionException e) {
            System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
        }
    }

    static class MyTask implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println(1/1);
            return "succeed";
        }
    }
}

輸出:
1
stringFutureTask返回結果:succeed
Process finished with exit code 0

如果在MyTask.call()中發送異常,比如:

package com.wx;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadSon2 {
    public static void main(String[] args) {
        FutureTask<String> stringFutureTask = new FutureTask<>(new MyTask());
        Thread thread = new Thread(stringFutureTask);
        thread.start();
        try {
            String s = stringFutureTask.get();
            System.out.println("stringFutureTask返回結果:"+s);
        } catch (InterruptedException e) {
            System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
        } catch (ExecutionException e) {
            System.err.println("stringFutureTask捕獲異常: " + e.getMessage());
        }
    }

    static class MyTask implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println(1/0);
            return "succeed";
        }
    }
}

輸出:
stringFutureTask捕獲異常: java.lang.ArithmeticException: / by zero
Process finished with exit code 0

四、Executors.callable()

import java.util.concurrent.*;

public class ThreadSon3 {
    public static void main(String[] args) {
        String result = "";
        Callable<String> callable = Executors.callable(new MyTask(),result);
        try {
            callable.call();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    static class MyTask implements Runnable{
        @Override
        public void run() {
            System.out.println(1/0);
        }
    }
}
輸出:
java.lang.ArithmeticException: / by zero
	at com.wx.ThreadSon3$MyTask.run(ThreadSon3.java:20)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at com.wx.ThreadSon3.main(ThreadSon3.java:10)
Process finished with exit code 0

五、Future

package com.wx;

import java.util.concurrent.*;

public class ThreadSon4 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        Future<?> future = executorService.submit(new MyTask());
        try {
            future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }finally {
            if (executorService!=null) {
                executorService.shutdown();
            }
        }
    }
    static class MyTask implements Runnable{
        @Override
        public void run() {
            System.out.println(1/0);
        }
    }
}

輸出
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.wx.ThreadSon4.main(ThreadSon4.java:10)
Caused by: java.lang.ArithmeticException: / by zero
	at com.wx.ThreadSon4$MyTask.run(ThreadSon4.java:26)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0
發佈了11 篇原創文章 · 獲贊 2 · 訪問量 2715
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章