异常和多线程
本章主要模拟几种多线程的情况,观察其它线程产生的异常,在主线程中是否能够捕获到。
模拟创建一个类,该类的work方法在某些条件下抛出了一个RuntimeException异常
public class Job{ int a=0; public Job(){}; public Job(int a){ this.a=a; } void work() { if(a==0){ throw new RuntimeException("不允许出现0值"); } System.out.println("第"+a+"个在工作"); } }
-
对于普通多线程
模拟创建普通异常,运行的结果是,catch里面的代码不会执行,也就是说主线程捕获不了子线程的异常。
public static void fun1(){ List<Job> jobs= Arrays.asList(new Job(1),new Job(2),new Job(),new Job(3),new Job(4),new Job(5)); try { Thread thread=new Thread( () -> jobs.forEach(job -> job.work()) ); thread.start(); }catch (Exception e){ System.out.println("捕捉到异常"+e.getMessage()); } }
-
对于stream
将集合转化为stream后,可以捕捉到异常。因为stream()方法并未创建多线程。
public static void fun2(){ List<Job> jobs= Arrays.asList(new Job(1),new Job(2),new Job(),new Job(3),new Job(4),new Job(5)); try { jobs.stream().forEach(job -> job.work()); }catch (Exception e){ System.out.println("捕捉到异常"+e.getMessage()); } }
-
对于parallelStream
将集合转化为parallelStream后,实验结果可以捕捉到异常,但异常消息有时候带了"RuntimeException"的描述。paralleStream本质也创建了内部的线程池,这里推测java对异常抛出机制做了一定的优化。
public static void fun3(){ List<Job> jobs= Arrays.asList(new Job(1),new Job(2),new Job(),new Job(3),new Job(4),new Job(5)); try { jobs.parallelStream().forEach(job -> job.work()); }catch (Exception e){ System.out.println("捕捉到异常"+e.getMessage()); } }
-
对于parallelStream自定义线程池
自定义ForkJoinPool给parallelStream使用,使用结果也是能够看到异常。
public static void fun4(){ List<Job> jobs= Arrays.asList(new Job(1),new Job(2),new Job(),new Job(3),new Job(4),new Job(5)); try { //使用自定义的parallelStream线程池 ForkJoinPool customThreadPool = new ForkJoinPool(4); customThreadPool.submit(()->jobs.parallelStream().forEach(job -> job.work())).invoke(); }catch (Exception e){ System.out.println("捕捉到异常"+e.getMessage()); } }