16、Java多线程
实现线程的方式有两种:继承Thread类和实现Runnable接口。继承Thread类时,在run方法中若想获得当前线程的相关信息,直接调用线程的实例方法或者静态方法即可,想获得当前线程,用this即可,且这种方式创建的线程之间不能共享线程类的实例变量;实现Runnable接口时,在具体创建一个线程对象时,需要将该Runnable实现类的对象传给Thread的构造方法当做其target来启动线程,本身不能直接启动线程,在run方法中如果想获得当前线程,需要调用Thread类的静态方法currentThread(),该方法返回当前正在执行的线程对象,而且这种方式创建的多条线程可以共享Runnable实现类中的实例变量。
线程的生命周期:新建——就绪(阻塞)——运行——死亡。当创建了一个线程类的实例后,该线程就处于新建状态,此时他和其他Java对象一样,仅仅由Java虚拟机为其分配了内存,并初始化了其成员变量的值。当线程调用了start()方法之后,线程就进入就绪状态,Java虚拟机就会为其创建方法调用栈和程序计数器,处于这个状态中的线程还没有执行,它只是代表了这个线程可以运行了,至于如何运行,取决于JVM里线程调度器的调度。(注意启动一个线程不要调用其run方法,也不要对已经处于启动状态或者死亡状态的线程再次调用start()方法)。如果处于就绪状态的线程获得了CPU,开始执行run方法中的线程执行体,则该线程处于运行状态。当一个线程处于运行状态之后,它一般不可能一直占用CPU,在其运行过程中需要被中断来是其他线程获得执行的机会,或者在手动让其让出CPU出来,这时线程会进入阻塞状态。一般发生如下情况,线程将会进图阻塞状态:
Ø
Ø
Ø
Ø
Ø
当正在执行的线程被阻塞之后,其他线程就可以获得执行的机会了。针对上面的几种情况,当发生如下的情况可解除上面的阻塞重新进入就绪状态:
Ø
Ø
Ø
Ø
Ø
调用sleep方法的线程会让线程进入阻塞状态,线程从阻塞状态只能进入就绪状态而无法进入运行状态。调用yield方法可以让运行状态的线程转入就绪状态。线程以以下几种方式之一结束后,将处于死亡状态:
Ø
Ø
Ø
控制线程:Thread提供了一个让线程等待另一个线程完成的方法:join方法。当在某个程序执行流中调用其他线程的join方法时,调用线程将被阻塞,直到被join的线程执行完成为止。
后台线程:在后台运行的,为其他线程提供服务的线程。如JVM的垃圾回收线程。当前台线程死亡后,后台线程也随即死亡。可以调用Thread类的setDaemon(true)来将某一个线程设为后台线程。
线程睡眠:调用Thread类的sleep方法,可以让当前线程阻塞。当线程调用sleep进入阻塞状态后,在其sleep时间里,该线程不会获得执行的机会,及时CPU空闲也不会执行。等时间经过之后,线程转入就绪状态。
线程让步:调用Thread的yield()方法,可以让当前线程暂停,但他不会阻塞该线程,只是将该线程转入就绪状态,暂停一下,让调度器重新调度线程。完全可能的情况是,当某个线程调用了yield方法之后,线程调度器又将其调度出来重新执行。实际上,当调用里该方法暂停以后,只有优先级与当前线程相同或者更高的就绪状态的线程才会获得执行的机会。
sleep与yield的区别:
²
²
²
²
改变线程的优先级:调用线程的setPriority()方法。一般不推荐直接写数值,而是设置成Thread提供的MAX/NORM/MIN_PRIORITY三个静态常量。这样具有更好的平台移植性。
线程的同步:线程同步一般有三种方法:synchronized块、synchronized方法和加lock锁。Synchronized方法只需在方法签名中加入该关键字即可,lock锁只要啊相应方法中调用lock对象的lock方法即可。二者的区别:synchronized
线程通信:Object类的wait()、notify()、notifyAll()三个方法可以实现线程间的协调通信。但这三个方法必须由同步监视器来调用。对于synchronized修饰的方法,因为该类的默认实例(this)就是同步监视器,所以可以在该方法中直接调用者三个方法;对于synchronized块,同步监视器是后面括号里的对象,所以必须使用该对象来调用这三个方法。
Ø
Ø
Ø
Callable和Future:Java中实现线程除了以上提到的两种方式以外,还有一种比较特殊的方式:实现Callable接口并实现call()方法,call()方法作为线程执行体且执行结束后会有返回值。用这种方式创建线程的方式如下:
Ø
Ø
Ø
Ø
注意:调用FutureTask对象的get方法来返回call方法的返回值时,将导致主线程被阻塞,知道call方法结束并返回为止。
线程池:使用线程池来执行线程任务的步骤如下:
Ø
Ø
Ø
Ø
17、Java异常处理机制
Java异常一般分为Exception和Error。Error指不能挽回的错误,如系统崩溃、虚拟机出错、动态链接失败等,通常会导致程序崩溃,Exception是可以处理的一些“例外”状况。他们都继承自Throwable父类。Exception分为RuntimeException和非RuntimeException,分别代表Runtime异常和Checked异常。异常可以用try-catch-finally捕捉处理。一般一个try块执行一次后最多只有一个catch块执行,就是匹配异常实例成功的那个在使用try-catch-finally时要注意一下几点:
Ø
Ø
Ø
Ø
Ø
Ø