大可制作:QQ群:31564239(asp|jsp|php|mysql)

Java Gossip: 线程生命周期

线程的四个主要周期状态如下所示:
线程生命周期

当您实例化一个Thread对象并执行start()之后,线程进入Runnable状态并开始执行run()方法。

虽然线程看起来像是同时执行,但事实上同一时间点上,还是只有一个线程在动作,只是线程之间切换的动作很快,所以看来像是同时执行。

线程有其优先权,由1(Thread.MIN_PRIORITY)到10(Thread.MAX_PRIORITY)默认是 Thread.NORM_PRIORITY(5),您可以使用Thread的setPriority()方法来设定线程的优先权,设定必须在1到10之间,否则会丢出IllegalArgumentException

优先权高的线程会先被执行完毕,然后才会轮到优先权低的线程,如果优先权相同,则输流执行(Round-robin方式)

决大多数的作业系统都支持timeslicing,简单的说就是作业 系统会为每个线程分配一小段CPU时间(quantum),时间一到就换下一个线程,即使现有的线程还没结束。对于不支持timeslicing的 作业系统,每一个线程必须完成后,才能轮到下一个线程,在这样的作业系统中,如果您想要让目前线程礼让一下其它线程,让它们有机会取得执行权,您 可以在调用绪行绪的yield()方法,例如:
public class SomeClass {
    // .....
        Thread thread = new Thread(new Runnable() {
            public void run() {
                // ....
                while(true) {
                    // ....
                    Thread.yield();  // 暂时让出执行权
                }
            }
        });
        thread.start();
    // ....
}

yield()方法让同样优先权的线程有被执行的机会,当线程执行yield()方法让出执行权时,它会再度加入线程的 排班,等待再度取得执行权,对于支持timeslicing的作业系统,调用yield()是不太需要的,因为作业系统会自动分配时间给线程轮流执行。

有几种状况会让线程进入Not Runnable状态(或是blocked状态)
  1. 调用sleep()
  2. 调用wait()
  3. 等待I/O完成

当线程在Not Runnable状态时,线程是可以被执行的,但有某些原因阻止它执行(例如等待使用者的输入),线程排班器将不分配执行时间给这个线程,直到以下 的几个情况让线程回到Runnable状态:
  1. 线程调用notify()
  2. 线程调用notifyAll()
  3. 线程调用interrupt()

当线程因为I/O而进入blocked状态,它必须等到I/O完成才可以离开这个状态。

最后,如果执行的工作完成(或发生异常)而离开run()方法,则线程执行完毕,进入Dead状态,您可以使用isAlive()方法来测试线程是否 存活。

如果您查询Java的线上API文件,您会发现有suspend()、resume()、stop()等方法,这些方法Java并不建议您使用,而且已经 被标示为"deprecated",这些方法建议您在需要的时候自行实现。

这边举个简单的例子,当您使用Thread.sleep()让线程暂停执行进入Not Runnable状态,您可以使用interrupt()让它离开Not Runnable状态,当使用sleep()暂时进入Not Runnable状态而您interrupt()时,会丢出InterruptedException异常对象,例如:

  • InterruptDemo.java 
package onlyfun.caterpillar;

public class InterruptDemo {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(99999);
}
catch(InterruptedException e) {
System.out.println("I'm interrupted!!");
//e.printStackTrace();
}
}
});

thread1.start();
thread1.interrupt(); // interrupt it right now
}
}

执行结果:
I'm interrupted! 

关于线程的wait()、notify()、notifyAll()等方法,在之后的文章中会陆续介绍。