zoukankan      html  css  js  c++  java
  • Java并发编程从入门到精通

    线程实现的三种方法:
    1、三种实现方式的简记:
     继承Thread类,重写run()方法;
     实现Runnable接口,重写run()方法,子类创建对象并作为Thread类的构造器参数;
     实现Callable接口,重写call()方法,子类创建对象并作为FutureTask类的构造器参数,FutureTask类创建对象并作为Thread类的构造器参数;
    2、三种实现方法的比较:
     继承Thread类:因为是单继承,所以扩展性不好;
     实现Runnable接口:接口可以多重实现;并且还可以再继承一个类;扩展性好
     实现Callable接口:Runnable无法返回结果,且不能抛出返回的异常;而Callable接口可以,Callable产生结果,FutureTask可以拿到结果,也可以捕获Callable抛出的异常;
     最常用的就是第二种,实现Runnable接口;

     1 /**
     2  * 实现线程的方法1:继承Thread类
     3  */
     4 package thread01;
     5 
     6 public class ThreadTest01
     7 {
     8     public static void main(String[] args)
     9     {
    10         ThreadDemo01 threadDemo01 = new ThreadDemo01();
    11         threadDemo01.start();
    12         
    13         // 使用下面方法也能达到效果
    14         /*Thread thread = new Thread(threadDemo01);
    15         thread.start();*/
    16         
    17         System.out.println("这是主线程:main结束");
    18     }
    19 }
    20 
    21 class ThreadDemo01 extends Thread
    22 {
    23     @Override
    24     public void run()
    25     {
    26         // 子类继承一个父类的时候,不是必须要重写父类的方法;但一个类实现一个接口的时候,这个类必须重写接口的方法;
    27         // 默认调用父类的run()方法,为什么要默认调用,因为你重写的时候,可能只是为了调用父类的run()方法;既然自己真的要重写,去掉即可;
    28         // super.run();
    29         
    30         try
    31         {
    32             // 必须加 try...catch...,即只能捕获,不能抛出异常
    33             Thread.sleep(1000);  // 使用sleep()方法模拟做了一些事(具体业务逻辑)
    34         } 
    35         catch (InterruptedException e)
    36         {
    37             e.printStackTrace();
    38         }
    39         
    40         System.out.println("这是线程ThreadDemo01");
    41     }
    42 }
    实现线程的方法1:继承Thread类
     1 /**
     2  * 实现线程的方法2:实现Runnable接口
     3  */
     4 package thread01;
     5 
     6 public class RunnableTest01
     7 {
     8     public static void main(String[] args)
     9     {
    10         ThreadDemo02 threadDemo02 = new ThreadDemo02();
    11         Thread thread = new Thread(threadDemo02);
    12         thread.start();
    13         
    14         System.out.println("这是主线程:main结束");
    15     }
    16 }
    17 
    18 class ThreadDemo02 implements Runnable
    19 {
    20     @Override
    21     public void run()
    22     {
    23         try
    24         {
    25             Thread.sleep(1000);
    26         } 
    27         catch (InterruptedException e)
    28         {
    29             e.printStackTrace();
    30         }
    31         
    32         System.out.println("这是线程ThreadDemo02");
    33     }
    34     
    35 }
    实现线程的方法2:实现Runnable接口
     1 /**
     2  * 实现线程的方法3:实现Callable接口
     3  * Callable和Future:一个可以产生结果,一个可以拿到结果
     4  */
     5 package thread01;
     6 
     7 import java.util.concurrent.Callable;
     8 import java.util.concurrent.ExecutionException;
     9 import java.util.concurrent.FutureTask;
    10 
    11 public class CallableTest01
    12 {
    13     public static void main(String[] args)
    14     {
    15         ThreadDemo03 threadDemo03 = new ThreadDemo03();
    16         FutureTask<String> futureTask = new FutureTask<String>(threadDemo03);
    17         Thread thread = new Thread(futureTask);
    18         thread.start();
    19         
    20         try
    21         {
    22             // 这里既可以捕获也可以抛出异常
    23             // 拿到Callable产生的结果
    24             System.out.println("获取线程返回的结果:" + futureTask.get());
    25         } 
    26         catch (InterruptedException | ExecutionException e)
    27         {
    28             e.printStackTrace();
    29         }
    30         
    31         System.out.println("这是主线程:main结束");
    32     }
    33     
    34     
    35     
    36 }
    37 
    38 class ThreadDemo03 implements Callable<String>
    39 {
    40 
    41     @Override
    42     public String call() throws Exception
    43     {
    44         try
    45         {
    46             // 这里不是必须要捕获异常,因为call方法默认抛出了异常
    47             Thread.sleep(1000);
    48         } 
    49         catch (Exception e)
    50         {
    51             e.printStackTrace();
    52         }
    53         
    54         // 上面futureTask不调用get()方法,call()方法也会执行(下面这句话也会执行),但肯定拿不到返回结果了
    55         System.out.println("这是线程ThreadDemo03");
    56         
    57         return "线程ThreadDemo03执行完毕返回的结果";
    58     }
    59     
    60 }
    实现线程的方法3:实现Callable接口
     1 /**
     2  * Callable接口的使用:抛出异常
     3  */
     4 package thread01;
     5 
     6 import java.util.concurrent.Callable;
     7 import java.util.concurrent.ExecutionException;
     8 import java.util.concurrent.FutureTask;
     9 
    10 public class CallableTest02
    11 {
    12     public static void main(String[] args)
    13     {
    14         ThreadDemo04 threadDemo04 = new ThreadDemo04();
    15         FutureTask<String> futureTask = new FutureTask<String>(threadDemo04);
    16         Thread thread = new Thread(futureTask);
    17         thread.start();
    18         
    19         try
    20         {
    21             // 异常的捕获和抛出都是通过get()方法体现的,如果没有调用get()方法,main方法执行的时候不会抛出异常;
    22             System.out.println("获得线程返回的结果:" + futureTask.get());
    23         } 
    24         catch (InterruptedException | ExecutionException e)
    25         {
    26             System.out.println("线程抛出了异常!");
    27             e.printStackTrace();
    28         }
    29         
    30         // 如果没有上面的try...catch...语句块,结果只会输出下面一句话,不会出现异常
    31         System.out.println("这是主线程:main结束");
    32     }
    33 }
    34 
    35 class ThreadDemo04 implements Callable<String>
    36 {
    37     @Override
    38     public String call() throws Exception
    39     {
    40         int sum = 1 / 0;
    41         System.out.println("sum = " + sum);
    42         
    43         return "线程ThreadDemo04执行完毕返回的结果";
    44     }
    45     
    46 }
    Callable接口的使用:抛出异常

    Thread里面的属性和方法:

     1 /**
     2  * Thread类里面的属性和方法
     3  */
     4 package thread01;
     5 
     6 public class ThreadTest02
     7 {
     8     public static void main(String[] args)
     9     {
    10         ThreadDemo05 threadDemo05 = new ThreadDemo05();
    11         Thread thread = new Thread(threadDemo05);
    12         thread.start();
    13         
    14         // 返回当前正在执行的线程对象的引用
    15         Thread currentThread = Thread.currentThread();
    16         System.out.println("主线程的名称:" + currentThread.getName());
    17         System.out.println("主线程所在的线程组中活动线程的数量:" + Thread.activeCount());
    18         System.out.println("主线程的标识符:" + currentThread.getId());
    19         System.out.println("主线程的优先级:" + currentThread.getPriority());
    20         System.out.println("主线程的状态:" + currentThread.getState());
    21         System.out.println("主线程所属的线程组:" + currentThread.getThreadGroup());
    22         System.out.println("测试主线程是否处于活动状态:" + currentThread.isAlive());
    23         System.out.println("测试主线程是否为守护线程:" + currentThread.isDaemon());
    24     }
    25 }
    26 
    27 class ThreadDemo05 implements Runnable
    28 {
    29     @Override
    30     public void run()
    31     {
    32         try
    33         {
    34             Thread.sleep(3000);
    35         } 
    36         catch (InterruptedException e)
    37         {
    38             e.printStackTrace();
    39         }
    40         
    41         System.out.println("=================================");
    42         
    43         // 返回当前正在执行的线程对象的引用
    44         Thread currentThread = Thread.currentThread();
    45         System.out.println("当前线程的名称:" + currentThread.getName());
    46         System.out.println("返回当前线程所在的线程组中活动线程的数量:" + Thread.activeCount());
    47         System.out.println("返回当前线程的标识符:" + currentThread.getId());
    48         System.out.println("返回当前线程的优先级:" + currentThread.getPriority());
    49         System.out.println("返回当前线程的状态:" + currentThread.getState());
    50         System.out.println("返回当前线程所属的线程组:" + currentThread.getThreadGroup());
    51         System.out.println("测试线程是否处于活动状态:" + currentThread.isAlive());
    52         System.out.println("测试当前线程是否为守护线程:" + currentThread.isDaemon());
    53     }
    54     
    55 }
    Thread类里面的属性和方法

    线程的中断机制:
    1、详述:
     Java中断机制是一种协作机制,也就是说通过中断不能直接终止另一个线程,而需要被请求中断的线程自己处理中断,且该线程可以选择接受请求中断自己,也可以选择不接受请求不中断自己;
     每个线程都有一个boolean类型的标识(中断状态位),代表是否有中断请求(该请求可以来自所有线程,包括被中断的线程本身),如果有中断请求,该标志位会被设置为true;
    2、三个方法的比较:
     public void interrupt():
      用于中断线程;调用该方法仅仅只是将线程的中断状态位设为true,并不会真的停止线程,还是需要用户自己去监视线程的状态位并做处理;
      中断是通过调用Thread.interrupt()方法来做的;这个方法通过修改被调用线程的中断状态来告知那个线程,说它被请求中断了;对于非阻塞中的线程,只是改变了中断状态,即Thread.isInterrupted()将返回true;对于可取消的(不解)阻塞状态中的线程,比如等待在这些函数上的线程:Thread.sleep(),Object.wait(),Thread.join()等,这个线程收到中断信号后,会抛出InterruptedException,同时会把中断状态置回为false;
      当一个线程处于中断状态时(意思是它的中断状态位为true),如果再由wait、sleep以及jion三个方法引起的阻塞,那么JVM会将线程的中断标志重新设置为false,并抛出一个InterruptedException异常;
      本质作用:根据try-catch功能块捕捉jvm抛出的InterruptedException异常来做各种处理,比如如何退出线程;总之interrupt的作用就是需要用户自己去监视线程的状态位并做处理;
     public static boolean interrupted():返回线程的上次的中断状态,并清除中断状态(清除是什么意思,将true改为false,还是既不是true也不是false);
     public boolean isInterrupted():判断线程是否中断;

     1 /**
     2  * 线程的中断机制1
     3  */
     4 package thread01;
     5 
     6 public class InterruptTest01
     7 {
     8     public static void main(String[] args) throws InterruptedException
     9     {
    10         ThreadDemo06 threadDemo06 = new ThreadDemo06();
    11         Thread thread = new Thread(threadDemo06);
    12         System.out.println("启动线程...");
    13         thread.start();
    14         
    15         Thread.sleep(1000);
    16         
    17         System.out.println("请求中断线程...");
    18         // 这里的thread就是指子线程,但是是在主线程中执行这条语句的,所以叫主线程请求中断子线程
    19         thread.interrupt();
    20         System.out.println("判断被请求中断的线程是否被中断(判断中断标志位):" + thread.isInterrupted());
    21         
    22         Thread.sleep(1000);
    23         
    24         // 请求中断主线程(线程请求中断自己)
    25         Thread.currentThread().interrupt();
    26         // 判断主线程是否被请求中断
    27         System.out.println("判断主线程main是都被中断(判断中断标志位):" + Thread.currentThread().isInterrupted());
    28         
    29         System.out.println("应用程序执行完毕,退出...");
    30         
    31     }
    32 }
    33 
    34 class ThreadDemo06 implements Runnable
    35 {
    36     boolean flag = false;
    37     
    38     @Override
    39     public void run()
    40     {
    41         while(!flag)
    42         {
    43             System.out.println("线程开始执行...");
    44             
    45             long currentTime = System.currentTimeMillis();
    46             while(System.currentTimeMillis() - currentTime < 5000)
    47             {
    48                 // 让该循环持续一段时间,让上面打印语句执行次数少一点
    49             }
    50             
    51             System.out.println("判断当前线程是否被中断(判断中断标志位):" + Thread.currentThread().isInterrupted());
    52         }
    53         
    54         System.out.println("线程在中断请求下中断退出");
    55     }
    56 }
    57 
    58 /*
    59 运行结果:
    60 启动线程...
    61 线程开始执行...
    62 请求中断线程...
    63 判断被请求中断的线程是否中断(判断中断标志位):true
    64 应用程序执行完毕,退出...
    65 线程开始执行...
    66 线程开始执行...
    67 线程开始执行...
    68 线程开始执行...
    69 线程开始执行...
    70 线程开始执行...
    71 
    72 根据结果可以看出,主线程请求中断正在执行的子线程,只是将子线程的中断标志位改变了,并没有真正中断子线程;
    73 子线程根据自己的需要判断是否接受中断请求,可以接受中断,也可以接受不中断;
    74 本实例中子线程并没有被中断;
    75 */
    线程的中断机制1
     1 /**
     2  * 线程的中断机制2
     3  */
     4 package thread01;
     5 
     6 public class InterruptTest02
     7 {
     8     public static void main(String[] args) throws InterruptedException
     9     {
    10         ThreadDemo07 threadDemo07 = new ThreadDemo07();
    11         Thread thread = new Thread(threadDemo07);
    12         System.out.println("启动线程...");
    13         thread.start();
    14         
    15         Thread.sleep(5000);
    16         
    17         System.out.println("请求中断线程...");
    18         thread.interrupt();
    19         
    20         Thread.sleep(1000);
    21         System.out.println("判断被请求中断的线程是否被中断(仅判断中断标志位):" + thread.isInterrupted());
    22         
    23         System.out.println("应用程序退出!");
    24     }
    25 }
    26 
    27 class ThreadDemo07 implements Runnable
    28 {
    29     private boolean flag = false;
    30     
    31     @Override
    32     public void run()
    33     {
    34         while(!flag)
    35         {
    36             System.out.println("线程开始执行...");
    37             
    38             long currentTime = System.currentTimeMillis();
    39             while(System.currentTimeMillis() - currentTime < 1000)
    40             {
    41                 
    42             }
    43             
    44             // 需要线程自己处理中断请求
    45             if(Thread.currentThread().isInterrupted())
    46             {
    47                 break;
    48             }
    49         }
    50         
    51         System.out.println("线程在中断请求下中断退出!");
    52     }
    53 }
    54 
    55 /*
    56 运行结果:
    57 启动线程...
    58 线程开始执行...
    59 线程开始执行...
    60 线程开始执行...
    61 线程开始执行...
    62 线程开始执行...
    63 线程开始执行...
    64 请求中断线程...
    65 线程在中断请求下中断退出!
    66 判断被请求中断的线程是否被中断(仅判断中断标志位):true
    67 应用程序退出!
    68 
    69 根据结果可以看出:被请求中断的线程需要自己根据需要决定是否中断退出;
    70 */
    线程的中断机制2
     1 /**
     2  * 线程的中断机制3
     3  */
     4 package thread01;
     5 
     6 public class InterruptTest03
     7 {
     8     public static void main(String[] args) throws InterruptedException
     9     {
    10         ThreadDemo08 threadDemo08 = new ThreadDemo08();
    11         Thread thread = new Thread(threadDemo08);
    12         System.out.println("启动线程...");
    13         thread.start();
    14         
    15         Thread.sleep(2000);
    16         System.out.println("2秒后请求中断线程(线程还在休眠)...");
    17         thread.interrupt();
    18         
    19         Thread.sleep(1000);
    20         System.out.println("应用程序结束退出!");
    21         
    22     }
    23 }
    24 
    25 class ThreadDemo08 implements Runnable
    26 {
    27     @Override
    28     public void run()
    29     {
    30         try
    31         {
    32             System.out.println("线程正在休眠5秒钟...");
    33             Thread.sleep(5000);
    34             // Thread.currentThread().join(5000);
    35         } 
    36         catch (InterruptedException e)
    37         {
    38             System.out.println("线程休眠被打断,抛出异常...");
    39         }
    40     }
    41 }
    42 /*
    43 运行结果:
    44 启动线程...
    45 线程正在休眠5秒钟...
    46 2秒后请求中断线程(线程还在休眠)...
    47 线程休眠被打断,抛出异常...
    48 应用程序结束退出!
    49 
    50 根据结果可以看出:处于睡眠中(调用sleep()方法)的线程,如果被请求中断,就会抛出中断异常(InterruptedException)
    51 */
    线程的中断机制3

    线程的生命周期:
    1、线程生命周期的5中状态:
    (1)、新建(new Thread):此时线程有自己的内存空间,但并没有运行;且线程还不是活着的;
    (2)、就绪(runnable):线程已经被启动(具备了运行条件),正在等待被分配给CPU时间片(不一定会被立即执行,处于线程就绪队列);此时线程是活着的;
    (3)、运行(running):线程获得CPU资源正在执行任务(执行run()方法);此时除非线程放弃CPU或者有优先级更高的线程进入,线程将一直运行到结束;此时线程是活着的;
    (4)、阻塞(blocked):由于某种原因导致正在运行的线程让出CPU并暂停自己的操作(任务执行),即进入阻塞状态;此时线程还是活着的;阻塞原因如下:
      正在休眠:线程调用sleep(long t)方法进入休眠,休眠到指定时间后进入就绪状态;
      正在等待:线程调用wait()方法,可调用notify()方法回到就绪状态;
      被另一个线程所阻塞:调用suspend()方法,可调用resume()方法恢复;
    (5)、死亡(dead):当线程执行完毕或被其他线程杀死,线程就进入死亡状态;此时线程不可能再进入就绪状态等待执行;此时线程不是活着的;
      死亡原因如下:
       自然终止:正常运行run()方法后终止;
       异常终止:调用stop()方法让一个线程终止运行;
    2、与线程状态对应的常用方法:
    run():必须被重写,实现具体的业务功能;
    start():启动线程;
    sleep():释放CPU执行权,不释放锁;
    wait():释放CPU执行权,释放锁;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池(Waiting Pool)中,同时失去了对象锁,只是暂时失去对象锁,wait后(不解)还要返还对象锁;当前线程必须拥有当前对象的锁,如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常,所以wait()必须在同步块(synchronized block)中调用;
    notify()/notifyAll():唤醒在当前对象等待池中等待的第一个线程/所有线程;notify()/notifyAll()也必须拥有相同对象锁,否则也会抛出IllegalMonitorStateException异常;
    yied():使当前正在运行的线程临时暂停,让出CPU的使用权,让同等优先权的线程运行(但并不保证当前线程会被JVM再次调度,使该线程重新进入Running状态);如果没有同等优先权的线程,那么yied()方法将不会起作用;
    3、状态转换:
     新建 -> 就绪:
      start();
     就绪 -> 运行:
      获得CPU执行权;
     运行 -> 就绪:
      yield();
     运行 -> 阻塞:
      sleep()、wait()、join()、synchronized;
     阻塞 -> 就绪:
      sleep()结束、wait()结束、IO完成;
     运行 -> 死亡:
      正常结束、异常退出;

    守护线程:
     可以简单的理解为后台运行线程;
     进程结束,守护线程跟着自动结束,不需要手动的去关心和通知其状态;
     Java的垃圾回收是一个守护线程;
     当正在运行的线程都是守护线程时,Java虚拟机退出;
     JRE判断程序是否执行结束的标准是所有的前台运行线程执行完毕了,而不管后台线程的状态;
     当进程中所有非守护线程已结束或退出时,即使仍有守护线程在运行,进程仍将结束;

    线程组:

    ThreadLocal:
     当前线程副本;
     当使用 ThreadLocal 维护变量的时候,ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程对应的副本;从线程的角度看,目标变量就像是线程的本地变量;
     ThreadLocal在处理线程的局部变量的时候比synchronized同步机制解决线程安全问题更简单、更方便,且结果程序拥有更高的并发性;
     注意:使用ThreadLocal,一般都是声明在静态变量(没说局部变量)中,如果不断创建ThreadLocal而且没有调用其remove()方法,将会导致内存泄漏;

     1 /**
     2  * ThreadLocal的使用
     3  */
     4 package thread01;
     5 
     6 public class ThreadLocalTest01
     7 {
     8     // 通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
     9     // 可以不加static
    10     private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>()
    11     {
    12         // 默认的是protected修饰符
    13         // protected Integer initialValue() {};
    14         // 重写此方法,返回该线程变量的初始值
    15         public Integer initialValue()
    16         {
    17             return 0;
    18         }
    19     };
    20     
    21     // 获得当前变量
    22     public ThreadLocal<Integer> getThreadLocal()
    23     {
    24         return seqNum;
    25     }
    26     
    27     // 实现读取下一个序列值
    28     public int getNexNum()
    29     {
    30         seqNum.set(seqNum.get() + 1);
    31         return seqNum.get();
    32     }
    33     
    34     // 定义成员内部类
    35     // 这里加static只是为了能在main方法中使用
    36     private static class TestClient implements Runnable
    37     {
    38         private ThreadLocalTest01 tl;
    39         
    40         public TestClient(ThreadLocalTest01 tl)
    41         {
    42             this.tl = tl;
    43         }
    44         
    45         @Override
    46         public void run()
    47         {
    48             for(int i=0;i<3;i++)
    49             {
    50                 // 每个线程打出三个序列值
    51                 System.out.println("thread[" + Thread.currentThread().getName() + "] --> tl[" + tl.getNexNum() + "]");
    52             }
    53             
    54             // 每个线程用完的时候要记得删除
    55             tl.getThreadLocal().remove();
    56         }
    57         
    58     }
    59     
    60     public static void main(String[] args)
    61     {
    62         ThreadLocalTest01 threadLocalTest01 = new ThreadLocalTest01();
    63         
    64         // 三个线程共享threadLocalTest01,格子产生序列号
    65         TestClient testClient1 = new TestClient(threadLocalTest01);
    66         TestClient testClient2 = new TestClient(threadLocalTest01);
    67         TestClient testClient3 = new TestClient(threadLocalTest01);
    68         
    69         Thread thread1 = new Thread(testClient1);
    70         Thread thread2 = new Thread(testClient2);
    71         Thread thread3 = new Thread(testClient3);
    72         
    73         thread1.start();
    74         thread2.start();
    75         thread3.start();
    76     }
    77 }
    ThreadLocal的使用

    线程的异常处理:
     详解:
      run方法不允许抛出异常,所有的异常必须在run方法中进行处理;就是说run方法中可以抛出异常,但不能往run方法外抛出异常,在run方法里面抛出的异常也必须在run方法内处理掉;
      在run方法中,抛出的已检查异常(checked exception)必须使用try...catch...进行处理,否则报错,编译不通过;(不是在run方法中抛出已检查异常,则既可以使用try...catch...进行处理,也可以使用throws继续往上抛)
      在run方法中,虽然向外抛出未检查异常不会报错,但这样不合理(run方法中的异常应该在run处理);
     线程中处理异常的方法总结:
      不能直接在一个线程中抛出异常;
      如果是已检查异常(checked exception),推荐采用try...catch...块来处理;
      如果是未检查异常(unchecked exception),推荐方法:注册一个实现UncaughtExceptionHandler接口的对象实例来处理;
     线程中,处理未检查异常的方法的具体步骤总结:
      定义一个类实现UncaughtExceptionHandler接口,在需要实现的方法里面包含对异常处理的逻辑和步骤;
      定义一个线程,执行需要的业务逻辑功能;
      在创建和执行该子线程的方法中,在thread.start()语句前增加一个thread.setUncaughtExceptionHandler(自定义异常处理类对象)语句来实现异常处理逻辑的注册;

      1 /**
      2  * 线程中,对已检查异常的处理
      3  */
      4 package thread01;
      5 
      6 import java.io.FileWriter;
      7 import java.io.IOException;
      8 
      9 public class CheckedExceptionTest
     10 {
     11     public static void main(String[] args)
     12     {
     13         ThreadDemo09 threadDemo09 = new ThreadDemo09();
     14         Thread thread = new Thread(threadDemo09);
     15         thread.start();
     16     }
     17 }
     18 
     19 class ThreadDemo09 implements Runnable
     20 {
     21     @Override
     22     public void run()
     23     {
     24         // 不能在try中声明,这样会导致finally中无法只用;
     25         FileWriter fw = null;
     26         
     27         try
     28         {
     29             // 在线程的run()方法中,对于抛出的已检查异常,必须且只能使用try...catch...在run方法内部进行处理,不处理则直接报错(编译不过)
     30             // 抛出异常的原因:可能找不到文件路径;
     31             fw = new FileWriter("F:/ppt/text.txt");
     32         } 
     33         catch (IOException e1)
     34         {
     35             e1.printStackTrace();
     36         }  
     37         finally 
     38         {
     39             // 无论程序怎么运行,最后都要关闭流; 
     40             // 一旦路径有误,fw就会出现空指针异常,所以要先判断fw是否为空  
     41             if(null != fw)
     42             {
     43                 try
     44                 {
     45                     fw.close();
     46                 } 
     47                 catch (IOException e)
     48                 {
     49                     e.printStackTrace();
     50                 }
     51             }
     52         }
     53     }
     54     
     55     public void testCheckedException()
     56     {
     57         // 非run方法中抛出的已检查异常,既可以使用try...catch...进行捕获,也可以继续抛出;
     58         // 以下是使用try...catch...进行捕获处理
     59         
     60         // 不能在try中声明,这样会导致finally中无法只用;
     61         FileWriter fw = null;
     62         
     63         try
     64         {
     65             // 对于抛出的已检查异常,必须且只能使用try...catch...在run方法内部进行处理,不处理则直接报错(编译不过)
     66             // 抛出异常的原因:可能找不到文件路径;
     67             fw = new FileWriter("F:/ppt/text.txt");
     68         } 
     69         catch (IOException e1)
     70         {
     71             e1.printStackTrace();
     72         }  
     73         finally 
     74         {
     75             // 无论程序怎么运行,最后都要关闭流; 
     76             // 一旦路径有误,fw就会出现空指针异常,所以要先判断fw是否为空  
     77             if(null != fw)
     78             {
     79                 try
     80                 {
     81                     fw.close();
     82                 } 
     83                 catch (IOException e)
     84                 {
     85                     e.printStackTrace();
     86                 }
     87             }
     88         }
     89     }
     90     
     91     public void testCheckedException2() throws IOException  
     92     {
     93         // 非run方法中抛出的已检查异常,既可以使用try...catch...进行捕获,也可以继续抛出;
     94         // 以下是使用 throws 继续往外抛
     95         FileWriter fw = new FileWriter("F:/ppt/text.txt");
     96         
     97         if(null != fw)
     98         {
     99             fw.close();
    100         }
    101     }
    102     
    103 }
    线程中,对已检查异常的处理
     1 /**
     2  * 线程中,对未检查异常的处理
     3  */
     4 package thread01;
     5 
     6 import java.lang.Thread.UncaughtExceptionHandler;
     7 
     8 public class UncheckedExceptionTest
     9 {
    10     public static void main(String[] args)
    11     {
    12         ThreadDemo10 threadDemo10 = new ThreadDemo10();
    13         Thread thread = new Thread(threadDemo10);
    14         thread.setUncaughtExceptionHandler(new UncheckedExcepionHandlerDemo());
    15         thread.start();
    16     }
    17 }
    18 
    19 class ThreadDemo10 implements Runnable
    20 {
    21     // 在线程的run方法中,对于未检查异常:可以不处理;可以继续往外抛;也可以使用try..catch..进行捕获处理;
    22     @Override
    23     public void run() // throws NumberFormatException
    24     {
    25         // 抛出类型转换异常
    26         int result = Integer.parseInt("ijn");
    27         System.out.println(result);
    28     }
    29     
    30     public void testUncheckedException1()
    31     {
    32         // 在非run()方法中,对于未检查异常:可以不处理;可以继续往外抛;也可以使用try..catch..进行捕获处理;
    33         // 以下是不处理
    34         int result = Integer.parseInt("ijn");
    35         System.out.println(result);
    36     }
    37     
    38     public void testUncheckedException2()
    39     {
    40         // 在非run()方法中,对于未检查异常:可以不处理;可以继续往外抛;也可以使用try..catch..进行捕获处理;
    41         // 以下通过try..catch..进行捕获处理
    42         int result = 0;
    43         try
    44         {
    45             result = Integer.parseInt("ijn");
    46         } 
    47         catch (NumberFormatException e)
    48         {
    49             e.printStackTrace();
    50         }
    51         System.out.println(result);
    52     }
    53     
    54     public void testUncheckedException3() throws NumberFormatException
    55     {
    56         // 在非run()方法中,对于未检查异常:可以不处理;可以继续往外抛;也可以使用try..catch..进行捕获处理;
    57         // 以下是使用 throws 继续往外抛
    58         int result = Integer.parseInt("ijn");
    59         System.out.println(result);
    60     }
    61 }
    62 
    63 class UncheckedExcepionHandlerDemo implements UncaughtExceptionHandler
    64 {
    65     @Override
    66     public void uncaughtException(Thread t, Throwable e)
    67     {
    68         System.out.println("一个未检查异常被捕获...");
    69         System.out.println("线程id:" + t.getId());
    70         System.out.println("异常名称:" + e.getClass().getName() + ",异常信息:" + e.getMessage());
    71         System.out.println("异常栈信息:");
    72         e.printStackTrace(System.out);
    73         System.out.println("线程状态:" + t.getState());
    74     }
    75 }
    线程中,对未检查异常的处理
  • 相关阅读:
    Windows Server 2012 R2 英文版安装中文语言包教程
    远程连接提示要求的函数不受支持如何解决
    Authenticator App 两步验证会不会造成亚马逊账号关联?
    Linux环境下查看历史操作命令及清除方法(history -c)
    出现Strict Standards: Only variables should be passed by reference in的解决方法
    Mysql索引优化
    MySQL性能优化(四)-- MySQL explain详解
    接口性能指标TP90
    本地项目git初始化并提交远程仓库
    git强制推送命令
  • 原文地址:https://www.cnblogs.com/kehuaihan/p/8458278.html
Copyright © 2011-2022 走看看