1

我的消費者沒有按照我期望的方式工作。以下是我的真實計劃中發生的一件sscceUncaughtExceptionHandler行爲異常,然後凍結

  • 預計:
    1. 打印In finally!
    2. 打印About to print stacktrace
    3. 打印一個NullPointerException堆棧跟蹤。
  • 實際:
    1. 打印In finally!
    2. 坑,在sun.misc.Unsafe

計劃:

import java.lang.Thread.UncaughtExceptionHandler; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 

public class ThreadTest implements Runnable { 
    public static void main(String... args) { 
     ExecutorService service = Executors.newSingleThreadExecutor(new ThreadFactory() { 
        @Override 
        public Thread newThread(Runnable r) { 
         Thread newThread = new Thread(r); 
         newThread.setUncaughtExceptionHandler(new MyExceptionHandler()); 
         return newThread; 
        } 
       }); 
     service.submit(new ThreadTest()); 
    } 

    private static class MyExceptionHandler implements UncaughtExceptionHandler { 
     @Override 
     public void uncaughtException(Thread t, Throwable e) { 
      System.out.println("About to print stacktrace"); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void run() { 
     Object foo = null; 
     try { 
      while(!Thread.interrupted()) { 
       Thread.sleep(1000); 
       System.out.println(foo.toString()); 
       System.out.println("After npe!"); 
      } 
     } catch(InterruptedException e) { 

     } finally { 
      System.out.println("In finally!"); 
     } 
    } 
} 

回答

2

的Runnable運行中一個執行程序不會真的拋出會觸發該線程的未捕獲異常處理程序的異常。相反,Runnable包含捕獲Throwable的代碼。這是爲了使Future能夠返回從任務中拋出的異常。

正如@Gray在下面的評論中指出的,你的程序是「掛起」的,因爲線程池線程阻止程序退出。你的runnable已經完成,線程池線程正在等待一個新的任務。如果關閉線程池,程序將正常完成(或者使線程池線程守護進程)。

+0

爲什麼它會掛起? – durron597

+1

由於您尚未關閉執行程序服務@ durron597而導致掛起。 – Gray

+0

你可能應該使用'Callable',一旦你調用future.get()就會拋出NPE。 – Gray