线程的生命周期

来源:互联网 发布:淘宝一千零一夜观看 编辑:程序博客网 时间:2024/06/06 10:42

线程要经历新建(New) 就绪(Runnable) 运行(Running) 阻塞(Blocked) 死亡(Dead)5种状态

线程生命周期图

这里写图片描述


线程优先级调度

Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。

Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级


从运行状态到阻塞状态(sleep方法和join方法)

  1. 线程调用Thread类的静态方法sleep()方法主动放弃所占用的处理器资源
    static void sleep(long millis)
    static void sleep(long milis,int nanos)
    当前线程调用sleep()方法进入阻塞状态,在其睡眠时间内,该线程不会获得执行的机会!
    调用sleep()方法会抛出异常

  2. Thread提供了让一个线程等待另一个线程完成的方法——join()方法

当A线程执行到了B线程的join()方法时,A就会等待,等B线程都运行完,A线程才会运行。
调用join()方法会抛出异常

class Demo implements Runnable{ public void run() {  for(int x=1; x<100; x++)  {       System.out.println(Thread.currentThread().getName() + "..." + x);  } }}public class JoinDemo{ public static void main(String[] args) throws Exception {  Demo d = new Demo();  Thread t1 = new Thread(d);  Thread t2 = new Thread(d);  t1.start();  t1.join();  t2.start();  for(int x=1; x<100; x++)  {   System.out.println(Thread.currentThread().getName() + "..." + x);  } }}

主线程向下转时,碰到了t1.join(),t1要申请加入到运行中来,就要执行CPU执行权。这时候CPU执行权在主线程手里,主线程就把CPU执行权给放开,陷入冻结状态。活着的只有t1了,只有当t1拿着执行权把这些数据都打印完了,主线程才恢复到运行中来

如果t1.join()和t2.start()位置互换,又会怎样呢?主线程开启了t1,t2这时候cpu执行权还在主线程手里。当主线程碰到t1.join(),释放执行权,处于冻结状态。活着的t1,t2都具备执行资格,这时候CPU便对于t1和t2交替执行。主线程要等到t1结束后才能活,至于t2结不结束,与主线程没有丝毫关系。如果t1结束了,t2还没结束,主线程就会和t2争抢执行权。主线程碰到谁的join()他就等谁死了才会执行。


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

从运行状态到可运行状态(yield方法)

  1. yield()和sleep()比较相似,他也是Thread类提供的一个静态方法,也可以让当前正在执行的线程暂停一下,但他不会阻塞该线程,只是将该线程转入可运行状态
    完全可能的情况是:当某个线程调用了yield()方法,线程调度器又将其调度出来重新执行
    实际上当某个线程调用yield方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程高的处于就绪状态的线程才会获得执行的机会。
public class YieldTest extends Thread{    public YieldTest(String name){        super(name);    }    public void run(){        for(int i=0;i<50;i++){            System.out.println(getName()+" "+i);            if(i==20){                Thread.yield();            }        }    }    public static void main(String[] args){        YieldTest yt1=new YieldTest("高级");        //yt1.setPriority(MAX_PRIORITY);        yt1.start();        YieldTest yt2=new YieldTest("低级");        //yt2.setPriority(MIN_PRIORITY);        yt2.start();    }}

如果不取消对上面yt1,yt2优先级的设置,他两优先级相同。在调用yield以后()将执行权让给优先级相同的线程
如果取消对上面yt1,yt2优先级的设置,yt1的优先级大于yt2的优先级。在调用yield以后()降执行权让给同等优先级或者高等级优先级的线程。yt1继续执行。


后台线程

有一种线程是在后台运行的,他的任务是为其他的线程提供服务,这种线程被称为”后台线程”(Daemon Thread)又称为守护线程或者精灵线程。
JVM的垃圾回收装置就是典型的后台线程
如果所有前台线程都死亡,后台线程会自动死亡
public final void setDaemon(boolean on)

public class DaemonThread extends Thread{    public void run(){        for(int i=0;i<1000;i++){            System.out.println(this.getName()+" "+i);        }    }    public static void main(String[] args) {        DaemonThread t=new DaemonThread();        t.setDaemon(true);        t.start();        for(int i=0;i<20;i++){            System.out.println(Thread.currentThread().getName()+" "+i);        }    }}

可以发现后台线程很难运行到999,因为当主线程也就是唯一的前台线程执行完后,后台线程会自动关闭。

原创粉丝点击