Java线程状态与生命周期

前面我们介绍了创建线程的三种基本方法,学会如何创建和运行线程之后,接下来就是对线程生命周期的了解,本篇我们介绍Java线程的声明周期,并且使用一些案例演示声明周期的变化。在Thread类中,使用枚举类为Java线程定义了六种状态,代码如下:

public enum State {   
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

在上述状态中,NEW:初始状态,线程被构建,但是还没有调用 start 方法;RUNNABLED:运行状态,称为运行状态,JAVA 线程把操作系统中的就绪和运行两种状态统一称为“运行状态”,因为CPU是采取时间片的方式执行线程,当CPU将时间片分配制其他线程时,该线程就处于就绪状态,当该线程获取到时间片时,该线程处于运行状态。WAITING和TIMED_WAITING是等待状态,他们的区别是TIME_WAITING是超时等待状态,超时以后自动返回。TERMINATED表示终止状态,表示当前线程执行完毕,BLOCKED表示阻塞状态。我们可以使用图示表示线程状态之间的转换情况如下图,记住了下面的图例基本上就掌握了线程的声明周期。

下面我们针对上图对Java线程的生命周期进行演示,首先是NEW状态,在这之前我们先使用继承的方式创建两个线程,并且创建一个测试类,这是不再展示代码,可以参考线程的创建一篇博文。我们创建一个线程实例,然后输出其状态可以看到结果我NEW,代码如下:

static void  NewStateTest() {
    ThreadA ta = new ThreadA();
    //输出为NEW
    System.out.println(ta.getState());
}

 还是使用ThreadA实例,实例创建之后调用start()方法,启动线程,然后输出线程的状态,可以看到输出结束为RUNNABLE,代码如下所示:

static void runnableStateTest() {
    ThreadA ta = new ThreadA();
    ta.start();
    //输出为RUNNABLE
    System.out.println(ta.getState());
}

TERMINATED表示终止状态,表示当前线程执行完毕,我们调用start()方法,为了能够确保线程执行完毕,我们在主线程sleep一秒,代码如果所示,结果会输出TERMINATED

static void terminalStateTest() throws InterruptedException {
    ThreadA ta = new ThreadA();
    ta.start();
    Thread.sleep(1000);
    //输出为TERMINATED
    System.out.println(ta.getState());
}

WAITING和TIMED_WAITING都表示线程处于等待状态,区别是WAITING状态的线程在没有被唤醒之前一直处于等待中,而TIMED_WAITING则有一个等待超时的时间。线程处于WAITING状态是因为调用了Object.wait()、Thread.join()、LockSupport.park()方法,相对应的需要调用Object.notify()、Object.notifyAll()或者LockSupport.unPark()去唤醒等待中的线程。比如一个线程调用了Object.wait()方法将会一直等待,直到另一个线程调用Object.notify()或者Object.notifyAll()方法。一个调用Thread.join()的线程将会等待指定的线程终止才会被唤醒。TIMED_WAITING的用法与WAITING类似,他提供了Object.wait(long time)、Thread.sleep(long time)、Thread.join(long time)、LockSupport.partNanos和parkUtil方法。如下是我们使用wait和notify的一个案例:

public class ThreadB extends Thread{
    public Object lock = null;
    public ThreadB(Object lock) {
	this.lock = lock;
    }
    @Override
    public void run() {
	synchronized (lock) {
	    try {
		System.out.println("lock.wait()方法调用 ");
                //调用Object.wait方法,线程处于WAITING状态
		lock.wait();
		System.out.println("Thread B 运行 ");
	} catch (InterruptedException e) {
				
	}
    }
    }
}
static void waitingStateTest() throws InterruptedException {
    Object lock = new Object();
    ThreadB tb = new ThreadB(lock);
    tb.start();
    Thread.sleep(1000);
    //输出为WAITING
    System.out.println(tb.getState());
    Thread.sleep(2000);
    synchronized (lock) {
        //调用Object.notify()方法通知线程继续运行
        lock.notify();
    }	
}

上面的示例中需要注意的是Object.wait和Object.notify()都是在synchronized方法块中,这设计到线程的底层原理,这里不做多的介绍,需要记住的是如果不使用synchronized方法块中会抛出 java.lang.IllegalMonitorStateException异常。其他另外的方法这里不做示例,可以自行实验。

BLOCKED表示堵塞状态,处于阻塞状态的线程正在等待监控锁进入同步块/方法或调用Object\wait()后重新进入同步块/方法会变成BLOCKED状态。我们使用下面的示例演示BLOCK状态。我们再创建线程C。同时将THREADB中的wait改为sleep(5000)

public class ThreadC extends Thread{
    public Object lock = null;
    public ThreadC(Object lock) {
	this.lock = lock;
    }
    @Override
    public void run() {
        synchronized (lock) {
	    try {
		System.out.println("Thread C 运行 ");
	    } catch (Exception e) {
				
		}
	    }
    }
}

我们创建测试类如下,可以输出结果C线程的状态为BLOCKED。

static void blockedStateTest() throws InterruptedException {
    Object lock = new Object();
    ThreadB tb = new ThreadB(lock);
    ThreadC tc = new ThreadC(lock);
    tb.start();
    Thread.sleep(1000);
    tc.start();
    Thread.sleep(1000);
    //输出为BLOCKED
    System.out.println(tc.getState());	
}

学习线程的状态和生命周期有助于对整个线程的运行过程的把握,也有助于后面更加深入线程的学习,比如synchorized等锁的学习。在学习完锁之后,我们或许就会理解为和Object.wait()方法要放在synchronized方法块中使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值