线程的生命周期

一般而言,线程的生命周期中有5个状态:1.New(新建)状态  2.Runnable(就绪也叫可运行)状态 3.Running(运行)状态 4.Blocked(阻塞)状态 5.Dead(死亡)状态

 当在程序中使用new来创建一个线程时,我们称该线程处于一个New(新建)状态,此时该线程并未运行,只有调用该线程的start()方法时,该线程才会被运行,此时线程进入Runnable(可运行)状态。但是进入Runnable状态的线程并不一定会立即运行,至于该线程到底什么时候才会运行是由JVM来决定的。取得运行权的线程会进入Running(正在运行)状态。当一个Running状态的线程调用yield()方法时,该线程会让出运行权,由Running状态直接变为Runnable状态,等待JUVM重新分配运行权。需要注意的是,yield()方法只会让步于优先级相同或更高的线程,而低优先级的线程不会因为一个线程调用了yield()方法而获得运行机会。一个Running状态的线程运行也可能会被打断,当调用sleep()方法后该线程会进入Blocked(阻塞)状态,在指定等待时间到达之后再变为Runnable状态。除此之外,当一个线程调用join()方法时,也会使当前Running状态的线程变为Blocked状态,原本运行的线程会在调用join()方法的线程执行完毕后再执行。一个正在运行的线程有可能因为无法取得某个对象的对象锁而无法处于Running状态,此时该线程会由Running状态被丢到该对象的锁池(Lock Pool)中,并等待取得对象锁,取得对象锁后该线程会变为Runnable状态。当线程的run()方法运行完成后,该线程就进入了Dead(死亡)状态,进入死亡状态的线程无法再被运行了,调用一个已经死亡的线程的start()方法,则会出现IllegalThreadException。

  Object类提供了三个与多线程相关的方法wait()、notify()、notifyAll(),需要注意的是,使用这三个方法前,线程必须获得对象锁。也就是说,线程必须处于同步块或者同步方法中。当线程遇到了wait()方法时,该线程就必须释放出该对象的对象锁,并进入该对象的等待池(Wait Pool)中等待。运行的程序可能会有多个线程因为碰到了wait()方法而在等待池中等待。此时,如果某个使用该对象的线程碰到了notify()方法,那么在对象的等待池中的第一个碰到了wait()方法的线程就会被转移到该对象的锁池中,继续等待取得该对象的对象锁。而如果使用该对象的线程碰到了notifyAll()方法,那么在该对象的等待池中所有的线程都会被转移到该对象的锁池中,而优先权最高的线程会先取得对象锁。

综上所述,归纳出如下所示的线程状态图:

需要注意的是,Blocked Pool(阻塞池)是系统所有的,每个JAVA程序只能有一个阻塞池,而锁池和等待池是对象所有的,一个java程序可以有多个对象,所以可以有多个锁池和等待池。

 

 

线程之间相互通讯的典型问题就是生产者和消费者的问题。下面以一个类似的例子来说明线程之间相互通讯的机制,这种机制也成为"监控器模型"。

例如:有两个线程,一个输出A,一个输出B,让他们交替输出A和B,每个线程输出10次。代码如下:

/**两个线程的共享资源类,创建该类的一个对象,在两个线程中操作同一个对象,为了保证安全性,就要实现线程同步,为了保证交替输出AB,就要让两个线程之间互相通讯*/
public class Communication {
    public static void main(String[] args) {
        Communication com=new Communication();
        new Th1(com);
        new Th2(com);
    }
    private boolean flag=true;


    public boolean getFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
    
}


class Th1 implements Runnable{
    private Communication com;
    public Th1(Communication com){
        this.com=com;
        new Thread(this).start();
    }
    @Override
    public void run() {
        for (int count = 1; count <= 10;) {
            synchronized (com) {//同步块,锁定共享资源对象,即Communication com对象
                if (com.getFlag()) {//当flag为true时,输出结果,输出完毕后,将flag置为false,并且释放对象锁,唤醒等待取得对象锁的线程。
                    System.out.println("A"+count);
                    count++;       //输出次数自增
                    com.setFlag(false);//重新设置flag
                    com.notify();    //唤醒等待取得对象锁的线程
                } else {//当flag为true时,释放对象锁,并等待重新获得对象锁
                    try {
                        com.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}

class Th2 implements Runnable{
    private Communication com;
    public Th2(Communication com){
        this.com=com;
        new Thread(this).start();
    }
    @Override
    public void run() {
        for (int count = 1; count <=10;) {
            synchronized (com) {//同步块,锁定共享资源对象,即Communication com对象
                if (!com.getFlag()) {//当flag为false时,输出结果,输出完毕后,将flag置为true,并且释放对象锁,唤醒等待取得对象锁的线程。
                    System.out.println("B"+count);
                    count++;       //输出次数自增
                    com.setFlag(true);//重新设置flag
                    com.notify();       //唤醒等待取得对象锁的线程
                } else {//当flag为true时,释放对象锁,并等待重新获得对象锁
                    try {
                        com.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}

posted @ 2016-10-17 20:14  skip_2_my_lou  阅读(310)  评论(0编辑  收藏  举报