Java线程的运行状态(线程的生命周期)


 

 

 

新建和就绪状态

当程序使用new关键字创建了一个线程后,该线程就处于新建状态. JVM为Thread对象分配内存.初始化其成员变量的值.

 

线程对象调用start()方法之后,该线程处于就绪状态. JVM会为其创建方法调用栈和程序计数器.

就绪状态的线程并没有开始运行,它只是表示该线程可以运行了. JVM的线程调度器调度该线程运行.

 

注意:

1.调用start()启动线程之后,run()方法才会被看作线程执行体.

2.直接调用run()方法,则run()方法就只是一个普通方法.

 

 

运行和阻塞状态

就绪状态的线程获得了CPU,开始执行run方法的线程执行体.则该线程处于运行状态.

线程在执行过程中可能会被中断,以使其他线程获得执行的机会,线程调度取决于底层平台采用的策略.

 

现代桌面和服务器操作系统一般都采用抢占式策略。一些小型设备如手机则可能采用协作式调度.

抢占式策略的系统:系统给每个可执行的线程一个小时间段来处理任务;当该时间段用完,系统会剥夺该线程所占有的资源,让其他线程获得执行机会.在选择下一个线程时,系统会考虑线程的优先级.

 

线程进入阻塞状态:

1.线程调用sleep方法主动放弃所占用的处理器资源.

2.线程调用了一个阻塞式的IO方法,该方法返回之前,该线程被阻塞.

3.线程试图获得一个同步监视器,但同步监视器正被其他线程所持有.

4.线程在等待某个通知(notify).

5.线程调用了线程的suspend方法将线程挂起.不过这个方法容易导致死锁,所以程序应该尽量避免使用该方法.

 

阻塞线程重写进入就绪状态:

1.调用sleep方法的线程经过了指定的时间.

2.线程调用的阻塞式IO方法已经返回.

3.线程成功地获得了试图取得同步监视器.

4.线程正在等待某个通知时,其他线程发出了一个通知.

5.处于关闭状态的线程被调用了resume恢复方法.

 

 

线程死亡

线程在以下情况下死亡:

run()方法执行完成,线程正常结束.

线程抛出一个未捕获的Exception或Error.

直接调用该线程的stop()方法来结束该线程.该方法容易导致死锁,通常不推荐使用.

 

Thread对象的isAlive()方法,查看线程是否死亡。

 

注意:

死亡的线程不能再用start()方法重新启动。

一个线程的start()方法不能两次调用。

 

 

 

线程睡眠:sleep

sleep方法,将线程转入阻塞状态.时间到即再转入就绪状态.

 

 

线程让步:yeild

yeild()方法,将线程转入就绪状态。该方法让线程暂停一下,让系统重新调度一次。

 

 

sleep方法和yeild方法的区别:

sleep方法暂停期间不会给其他线程执行机会.

sleep方法会将线程转入阻塞状态,知道经过阻塞时间才会转入就绪状态.yeild直接把线程转入就绪状态.

sleep方法抛出InterruptedException异常,所以调用sleep()时要捕捉或抛出异常.而yeild()方法则没有声明抛出任何异常.

sleep方法比yeild法那个发有更好的移植性,通常不要依靠yeild来控制并发线程的执行.

 

join线程

在某个线程的执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join方法加入的join线程完成为止。

例:

public class TestJoin {
  public static void main(String[] args) {
    MyThread2 t1 = new MyThread2("abcde");
    t1.start();
    try {
    	t1.join();
    } catch (InterruptedException e) {}
    	
    for(int i=1;i<=10;i++){
      System.out.println("i am main thread");
    }
  }
}
class MyThread2 extends Thread {
  MyThread2(String s){
  	super(s);
  }
  
  public void run(){
    for(int i =1;i<=10;i++){
      System.out.println("i am "+getName());
      try {
      	sleep(1000);
      } catch (InterruptedException e) {
      	return;
      }
    }
  }
}

 

 

 

 

 

线程优先级

每个线程都有优先级.优先级高的线程获得较多的执行机会.

默认情况下,main线程具有普通优先级.

每个线程默认优先级与创建它的父线程具有同样的优先级. 

 

Java提供的优先级范围是1~10.默认优先级为5.

Thread提供静态常量:

static int MAX_PRIORITY 线程可以具有的最高优先级。 值为10.

static int MIN_PRIORITY 线程可以具有的最低优先级。值为1.

static int NORM_PRIORITY 分配给线程的默认优先级。值为5.

 

注意:

不同操作系统的优先级不同.应尽量避免直接为线程指定优先级,而应使用以上三个静态常量类设置优先级.

 

 

 

 

后台线程

运行在后台,用于为其他线程提供服务.又称为”守护线程”.

如果所有前台线程死亡,后台线程也会死亡.

 

调用Thread对象的setDeamon(true)方法可以将指定线程设置成后台线程.

所有前台线程死亡时,后台线程随之死亡.

 

Thread对象的isDeamon()方法用于判断指定线程是否为后台线程.

 

说明:

main方法的主线程是前台线程.

前台线程创建的线程默认是前台线程.

后台线程创建的线程默认是后台线程.

 

 

 

停止线程

需要停止线程不要去调用stop()方法。而是为线程类设置一个运行标志符。

例:

public class TestThread4 {	
	public static void main(String args[]){
		Runner4 r = new Runner4();
       	Thread t = new Thread(r);
        t.start();
        for(int i=0;i<100000;i++){
        	if(i%10000==0 & i>0)
        		System.out.println("in thread main i=" + i);
        }
        System.out.println("Thread main is over");
        r.shutDown();
        //t.stop();
    }
}

class Runner4 implements Runnable {
  private boolean flag=true;
  
	public void run() {
		int i = 0;
		while (flag==true) {
			System.out.print(" " + i++);	
		}
	}
	
  public void shutDown() {
		flag = false;
  }
}

 

 

 

 

 

 

 
  • 大小: 31.2 KB
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值