Java中线程的状态

目录

引言

1.NEW(新建状态) 

 2.RUNNABLE(可运行状态)

3. TERMINATED(消亡状态)

4.TIMEDWAITING(计时等待状态)

5. WAITING(无限等待状态)

6. BLOCKED(阻塞状态)

 END


引言

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,有几种状态呢?在API中 java.lang.Thread.State 这个枚举中给出了六种线程状态:

这里先列出各个线程状态发生的条件,下面将会对每种状态进行详细解析

线程状态

导致状态发生条件

NEW(新建)

线程刚被创建,但是并未启动。还没调用start方法。

RUNNABLE(可运行)

线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理器。

BLOCKED(锁阻)

当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。

WAITING(无限等待)

一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。

TIMED_WAITING(计时等待)

waiting状态,有几个方法有超时参数,调用他们将进入Timed  Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep Object.wait

TERMINATED(被终止)

因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

1.NEW(新建状态) 

一个线程创建好后,启动之前就处于该状态。

NEW状态只会出现一次。

 代码示例如下:

import java.lang.Thread.State;

public class test01 {

	public static void main(String[] args) throws InterruptedException {

		Thread t = new Thread();
        //获取线程的状态	
		State state = t.getState();
		System.out.println(state);
		
		t.start(); //启动线程
	}

}

运行结果:

NEW

 2.RUNNABLE(可运行状态)

简单来说线程正在执行任务就处于该状态。

代码示例如下:

import java.lang.Thread.State;

public class test02 {

	public static void main(String[] args) throws InterruptedException {
		//创建Runnable类型的对象
		Runnable r = new Runnable() {
			@Override
			public void run() {
			for(;;);//死循环,测试用,不建议平时写
				}
			};
				
			Thread t = new Thread(r);
			t.start();
			
            //保证执行下面代码的时候,子线程已经启动并且开始执行run方法中的代码	
			Thread.sleep(100);
			State s = t.getState();
			System.out.println(s);

	}

}

运行结果:

RUNNABLE

3. TERMINATED(消亡状态)

线程执行任务完,线程销毁后,就处于该状态。

TERMINATED状态只会出现一次。

示例代码如下:

import java.lang.Thread.State;

public class test03 {

	public static void main(String[] args) throws InterruptedException {

		Thread t = new Thread();
		
		t.start();
		//让主线程停留100毫秒
		Thread.sleep(100);//作业:让子线程执行结束
				
		state = t.getState();
		System.out.println(state);
	}

}

运行结果如下:

TERMINATED

4.TIMEDWAITING(计时等待状态)

简单来说一个线程正在执行sleep方法,就处于该状态。调用了sleep方法之后,当前执行的线程就进入到休眠状态,其实就是所谓的Timed    Waiting(计时等),那么我们通过一个案例加深对该状态的一个理解。

示例代码如下:

import java.lang.Thread.State;
public class test04 {

	public static void main(String[] args) throws InterruptedException {
		//创建Runnable类型的对象
				Runnable r = new Runnable() {
					@Override
					public void run() {
						try {
							Thread.sleep(30000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println("aaaaaaaaa");
					}
				};
				
				Thread t = new Thread(r);
				t.start();
				
				Thread.sleep(100);//保证执行下面代码的时候,子线程已经启动并且开始执行run方法中的代码
				State s = t.getState();
				System.out.println(s);

	}

}

运行结果:

TIMED_WAITING
aaaaaaaaa

sleep方法的使用注意事项:

  1. 进入 TIMED_WAITING 状态的一种常见情形是调用的 sleep 方法,单独的线程也可以调用,不一定非要有协作关系。
  2. sleep与锁无关,线程睡眠到期自动苏醒,并返回到Runnable(可运行)状态。
  3. 为了让其他线程有机会执行,可以将Thread.sleep()的调用放线程run()之内。这样才能保证该线程执行过程中会睡眠

 

5. WAITING(无限等待状态)

 简单来说获取Lock锁对象失败,就处于该状态。

虽然我们之前没有遇到过这种状态,但并不妨碍我们进行一个简单深入的了解。我们通过一段代码来学习一下:

示例代码如下:

public class test05 {
	public static Object obj = new Object();

	public static void main(String[] args) {
	// 演示waiting
	new Thread(new Runnable() { 
	@Override
	public void run() { 
	while (true){
	synchronized (obj){ 
	try {
	System.out.println( Thread.currentThread().getName() +"=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象");
	obj.wait(); //无限等待
	//obj.wait(5000); //计时等待, 5秒 时间到,自动醒来
	
	} catch (InterruptedException e) 
		{ e.printStackTrace();
	}
	System.out.println( Thread.currentThread().getName() + "=== 从waiting状态醒来,获取到锁对象,继续执行了");
			}
		}
	}
  },"等待线程").start();
	new Thread(new Runnable() { @Override
		public void run() {
//			while (true){	//每隔3秒 唤醒一次

		try {
		System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 等待3秒钟"); Thread.sleep(3000);
		} catch (InterruptedException e) 
			{ e.printStackTrace();
		}
		synchronized (obj){
			System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 获取到锁对象,调用notify方法,释放锁对象");
			obj.notify();
			}
		  }
//		}
	  },"唤醒线程").start();
    }
 }

运行结果如下:

等待线程=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象
唤醒线程‐‐‐‐‐ 等待3秒钟
唤醒线程‐‐‐‐‐ 获取到锁对象,调用notify方法,释放锁对象
等待线程=== 从waiting状态醒来,获取到锁对象,继续执行了
等待线程=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象

通过上述案例我们会发现,一个调用了某个对象的 Object.wait 方法的线程会等待另一个线程调用此对象的Object.notify()方法 或 Object.notifyAll()方法。

当多个线程协作时,比如AB线程,如果A线程在Runnable(可运行)状态中调用了wait()方法那么A线程就进入Waiting(无限等待)状态,同时失去了同步锁。假如这个时候B线程获取到了同步锁,在运行状态中调用了notify()方法,那么就会将无限等待的A线程唤醒。注意是唤醒,如果获取到锁对象,那么A线程唤醒后就进入Runnable(可运行)状态;如果没有获取锁对象,那么就进入到Blocked(锁阻塞状态)。

6. BLOCKED(阻塞状态)

简单来说获取synchronized锁对象失败,就处于该状态。

一个正在阻塞等待一个监视器锁(锁对象)的线程处于这一状态。那么这个状态是非常好理解的了。比如,线程A与线程B代码中使用同一锁,如果线程A取到锁,线程A进入到Runnable状态,那么线程B就进入到Blocked锁阻塞状态。

这是由Runnable状态进入Blocked状态。除此Waiting以及Time Waiting状态也会在某种情况下进入阻塞状态,而这部分内容作为扩充知识点带领大家了解一下。

示例代码如下:

import java.lang.Thread.State;
public class test06 {

	public static void main(String[] args) throws InterruptedException {
		//创建Runnable类型的对象
				Runnable r = new Runnable() {
					@Override
					public void run() {
						synchronized (this) {
							//死循环
							for (;;) {
							}
						}
					}
				};
				
				Thread t1 = new Thread(r);
				Thread t2 = new Thread(r);
				//启动线程,执行run方法
				t1.start();
				t2.start();
				
				Thread.sleep(100);//保证执行下面代码的时候,子线程已经启动并且开始执行run方法中的代码
				
				State s1 = t1.getState();
				State s2 = t2.getState();
				//获取线程状态
				System.out.println(s2);
				System.out.println(s1);

	}

}

两个线程同时执行run方法中的代码,t1先进入线程执行循环,一直无法出来,导致t2获取synchronized锁对象失败,所以就处于阻塞状态。

运行结果:

BLOCKED

RUNNABLE

 END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值