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

来源:互联网 发布:小区网络监控设计方案 编辑:程序博客网 时间:2024/06/04 17:53
一、生命周期


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线程的概念、创建与启动(一))。



0 0