Java线程生命周期与基本操作(二)

本文深入探讨了Java线程的生命周期及其关键操作,包括新建、就绪、运行、阻塞、死亡等状态,以及sleep、yield、join、interrupt、setDaemon、setPriority等方法的作用与使用场景。通过具体代码示例展示了这些操作如何影响线程的行为,并强调了避免使用过时方法的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、生命周期


1、当新建(new Thread)一个线程时,便进入新建的状态。

2、当线程调用start()方法后便进入就绪状态,进入线程池,等待系统调用。

3、系统空闲时,便会从线程池当中取出该线程运行执行run()方法,此过程不受程序控制。

4、运行中的线程调用yield()方法便会返回就绪状态。

5、运行中的线程执行sleep()方法、线程等待一个异步的操作结果(如等待某个notify)、线程调用了suspend方法(已过时)就会进入阻塞状态。

6、run()方法结束后,线程死亡,或者调用了stop()(已过时)、destory()(已过时)方法。 

二、常见操作(sleep、wait、yield、join、interrupt、setDaemon、setPriority)

在API文档中可以查看到很多对线程操作的方法,但是有很多已经Deprecated,需要熟悉的方法就是sleep、wait、yield、join、setDaemon、setPriority等。

1、sleep()方法,进程休眠程序,调用此方法后,进程进入阻塞状态,休眠时间到了,便会从新运行。

eg1:

public class test5 {
     
     public static void main(String args[]){
            for( int i = 0 ; i < 100 ; i++){
                System. out.println( "helloworld");
                 try {
                     Thread. sleep(1000);
                } catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                     e.printStackTrace();
                }
           }
     }

}

此程序每隔1s打印一次helloworld。
注:
     由于系统不一定就能在休眠时间到了就立即恢复程序的执行,所以间隔时间往往是大于1秒的。
     sleep函数必须写在线程本身的run()方法中,才能保证在该线程执行过程中睡眠。

VIP:sleep是静态方法(不需要实例化就能使用),最好不要用Thread的实例对象调用它,因为它睡眠的始终是当前正在运行的线程,而不是调用它的线程对象,它只对正在运行状态的线程对象有效,不属于某一个特定的线程实例

eg2:

MyThread myThread = new MyThread();
     try {
          myThread.sleep(10000);//在这里,实际上睡眠的是主线程
    } catch (InterruptedException e) {
                e. printStackTrace();
    }

2、yield()方法,线程让步方法,执行该方法后,线程重新返回就绪状态,等待系统重新调用。
eg3:
class MyThread extends Thread{
     String str;
      public MyThread(String str) {
            // TODO Auto-generated constructor stub
            this. str = str;
     }

      @Override
      public void run() {
            // TODO Auto-generated method stub
            for( int i = 0; i<100; i++ ){
                System. out.println( str + "第" +i + "次");
                 try {
                      sleep(1000);
                } catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                     e.printStackTrace();
                }
           }
            super.run();
     }
}

class MyThread2 extends Thread{
     String str;
      public MyThread2(String str) {
            // TODO Auto-generated constructor stub
            this. str = str;
     }

      @Override
      public void run() {
            // TODO Auto-generated method stub
            for( int i = 0; i<100; i++ ){
                 if(i%2==0){
                      this .yield();
                }
                System. out.println( str + "第" +i + "次");
                 try {
                      sleep(1000);
                } catch (InterruptedException e) {
                      // TODO Auto-generated catch block
                     e.printStackTrace();
                }
           }
            super.run();
     }
}

public class test5 {
     
      public static void main(String args[]){
           
           MyThread firstThread = new MyThread( "this is firstThread");
           MyThread2 secondThread = new MyThread2( "this is secondThread");
           
           secondThread.start();
           firstThread.start();
     }

}

执行该方法后,可以看到当i是偶数的,基本上都是firstThread先执行。

总结与sleep()方法的区别,返回线程状态不同sleep需要catch InterruptedException 的异常

3、join()方法


当线程2必须等线程1执行完了再执行时,就可以合并这两个线程为一个线程,使用join方法完成操作。
eg4:

public class test6 { 
    public static void main(String[] args) throws InterruptedException { 
        MyThread3 thread= new MyThread3(); 
        thread.start(); 
        thread.join(1); //将主线程加入到子线程后面,不过如果子线程在1毫秒时间内没执行完,则主线程便不再等待它执行完,进入就绪状态,等待 cpu调度 
        for( int i=0;i<30;i++){ 
            System. out.println(Thread. currentThread().getName() + "线程第" + i + "次执行!" ); 
        } 
    } 
}

class MyThread3 extends Thread { 
    @Override 
    public void run() { 
        for ( int i = 0; i < 1000; i++) { 
            System. out.println( this.getName() + "线程第" + i + "次执行!" ); 
        } 
    } 
}

结果:



4、setPriority()方法,除了可以使用sleep、yield方法一定程序上(精确的控制不能实现,是由系统决定的)控制线程执行的先后顺序,还有使用设置优先级的方法。
eg5:

class thread01 extends Thread{
     
     thread01( int por){
            this.setPriority(por);
     }
     
      @Override
      public void run() {
            for( int i = 0; i<100; i++){
                System. out.println( "thread01");
           }
            super.run();
     }
}

class thread02 extends Thread{
     
     thread02( int por){
            this.setPriority(por);
     }
     
      @Override
      public void run() {
            for( int i = 0; i<100; i++){
                System. out.println( "thread02");
           }
            super.run();
     }
}

public class test7 {
      public static void main(String[] agrs){
           thread01 t01 = new thread01(1);
           thread02 t02 = new thread02(10);
           t01.start();
           t02.start();
     }
}

可以看到,在t01执行完了之后,t02才执行。

5、setDaemon方法,设置线程为守护线程,守护线程的优先级一般是比用户线程的优先级低的。详见(Java线程的概念、创建与启动(一))。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值