JAVA课程论文
多线程和异常处理
本学期学习了《面向对象与java程序设计》这门课程,收获甚多,感觉自己不仅仅掌握了一门新的计算机语言,同时也使自己关于计算机编程的理解进一步深入,自己可以通过一种新的方式来实现以往所需要的程序效果,不仅如此,还可以实现更为复杂的效果。这里,关于java中的多线程和异常处理两方面的内容作出自己的一些理解和学习心得。
在Java中,实现多线程的类是Thread类。定义Thread对象有两种方法,一种是直接继承Thread,另一种是实现Runable接口。两者都需要写run方法。而且,无论是哪一种方法,生成的线程都是Thread。也就是说,其实线程类只有一种,那就是Thread。线程有线程自己的特性,多线程提高了CPU利用率的同时,也带来了一些问题。因此,在学习多线程,其实就是学习多线程编程多带来哪些问题,以及如何去解决这些问题,使得多线程能够按照我们的意愿来执行。首先,线程有自己的状态,就像水也有自己的状态一样。水有气态,固态和液态;线程也有自己的状态,除了新建和死亡状态,就有等待/阻塞、准备、和运行 状态。 同样的,这些状态可以转换。线程个状态的转换是:准备可以进入运行,运行也可以进入准备;运行还可以进入等待/阻塞;但是等待/阻塞不能进入运行,等待/阻塞可以进入准备状态。
根据上面这几种状态,加上控制线程的函数,就可以控制线程了,这就叫作线程的调度。新建:就是利用Thread的构造函数定义一个线程。准备:当执行了Thread中的strat方法,及使得线程进入准备状态,随时可以进入运行状态。运行:当操作系统的调度器把CPU分给了这个线程,这个线程就进入了运行状态,也就是执行我们在线程中定义的run方法里面的内容。等待/阻塞:当一个线程的继续执行需要一个条件,但是该条件还不成熟,需要调度器来通知。而等待调度器发出通知的这段时间内,线程就进入了等待状态。当一个线程访问一个资源的时候,这个资源正被另外的线程访问,而这个资源是加了锁的,只允许一个线程访问。这时候,线程就进入了阻塞状态。死亡:当线程的run方法运行完之后,线程死亡,这是正常死亡;当线程方发生异常而没有捕获时,也会死亡,这是非正常死亡。不管是正常死亡还是非正常死亡,都是死亡。
控制线程:Thread提供了一个让线程等待另一个线程完成的方法:join方法。当在某个程序执行流中调用其他线程的join方法时,调用线程将被阻塞,直到被join的线程执行完成为止。
后台线程:在后台运行的,为其他线程提供服务的线程。如JVM的垃圾回收线程。当前台线程死亡后,后台线程也随即死亡。可以调用Thread类的setDaemon(true)来将某一个线程设为后台线程。
线程睡眠:调用Thread类的sleep方法,可以让当前线程阻塞。当线程调用sleep进入阻塞状态后,在其sleep时间里,该线程不会获得执行的机会,及时CPU空闲也不会执行。等时间经过之后,线程转入就绪状态。
线程让步:调用Thread的yield()方法,可以让当前线程暂停,但他不会阻塞该线程,只是将该线程转入就绪状态,暂停一下,让调度器重新调度线程。完全可能的情况是,当某个线程调用了yield方法之后,线程调度器又将其调度出来重新执行。实际上,当调用里该方法暂停以后,只有优先级与当前线程相同或者更高的就绪状态的线程才会获得执行的机会。
改变线程的优先级:调用线程的setPriority()方法。一般不推荐直接写数值,而是设置成Thread提供的MAX/NORM/MIN_PRIORITY三个静态常量。这样具有更好的平台移植性。
线程的同步:线程同步一般有三种方法:synchronized块、synchronized方法和加lock锁。Synchronized方法只需在方法签名中加入该关键字即可,lock锁只要啊相应方法中调用lock对象的lock方法即可。二者的区别:synchronized也有好处的,比如一些性能监控工具,可以监测到 synchronized的锁。无法监测到 Lock 的锁定,毕竟 Lock 的锁定是通过代码实现的,而synchronized是在 JVM 层面上实现的。要监控工具能监测到 Lock 的锁定那还需要有一段时日。另外,synchronized 在锁定时如果方法块抛出异常,JVM会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是Lock的话就享受不到 JVM 带来自动的功能,出现异常时必须在finally将锁释放掉,否则将会引起死锁。
由于同一进程的多个线程共享同一片存储空间,在带来方便的同时